多线程编程之原子锁

Posted 拙园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程编程之原子锁相关的知识,希望对你有一定的参考价值。

 在《多线程编程之数据访问互斥》一文中简单介绍了原子锁,这里再详细说一下原子锁的概念和用途。

(1)简单数据操作

  如果在一个多线程环境下对某个变量进行简单数学运算或者逻辑运算,那么就应该使用原子锁操作。因为,使用临界区、互斥量等线程互斥方式将涉及到很多操作系统调用和函数调用等,效率肯定不如原子操作高。比如有这样一个例子:

复制代码
unsigned int count = 0;
int data_process()
{
    if(/* conditions */){
         EnterCriticalSection(&cs);
         ++ count;
         LeaveCriticalSection(&cs);         
    }
}
复制代码

   这里只有简单的数学操作,完全可以应用操作系统提供的原子操作来替代,效率会高不少:

复制代码
unsigned int count = 0;
int data_process()
{
    if(/* conditions */){
        InterLockedIncrement (&count);       
    }
}
复制代码

(2)代码段中的互斥

  还是以临界区为例,比如在代码段中应用到了如下的临界区:

void data_process()
{
    EnterCriticalSection(&cs);
    do_something();
    LeaveCriticalSection(&cs);   
}

   这里其实也可以利用原子锁来代替临界区,实现方式如下:

复制代码
unsigned int lock = 0;
void data_process()
{
    while(1 == InterLockedCompareExchange(&lock, 1, 0));
    do_something();
    lock = 0;    
}
复制代码

   InterLockedCompareExchange方法的含义是:将第一个参数的值与第三个参数的值进行比较,如果相等则与第二个参数的值进行交换,如果不相等则不进行操作;返回值为第一个参数的初始值,该函数所进行的操作为原子操作,不会被多线程中断,可适用于所有CPU。

  上面的代码含义就是不断监测lock的值,当lock值为0时,InterLockedCompareExchange就会将其变为1,并执行do_something(),最后将lock还原为0。当然,如果lock此时为1,这个while循环就会不断地执行(“忙等”)。

  其实说到这里,我们就会发现这里有一个问题:如果另外有一个线程将lock变为1并且需要执行很长的时间,那么这里岂不成了疯等?没错,所以说这种原子锁方法适用于短时间操作线程的互斥场合,并不能替代所有系统互斥锁调用场合。临界区在此时就会表现得更有优越性。

以上是关于多线程编程之原子锁的主要内容,如果未能解决你的问题,请参考以下文章

C++11多线程 原子操作概念及范例

多线程编程之线程安全性的简介

Java多线程之原子操作类

高并发多线程安全之原子性问题CAS机制及问题解决方案

JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段

多线程编程之synchronized和Lock