mutex锁(自旋锁与互斥锁)

:暂无数据 2026-05-03 20:00:02 0
各位朋友,关于mutex锁的讨论一直很多,今天咱们不聊复杂的,就聚焦于自旋锁与互斥锁,用最直白的方式把它讲清楚。

本文目录

自旋锁与互斥锁

自旋锁:
是一种用于保护多线程共享资源的锁,与一般互斥锁(mutex)不同之处在于当自旋锁尝试获取锁时以忙等 待(busy waiting)的形式不断地循环检查锁是否可用。当上一个线程的任务没有执行完毕的时候(被锁住), 那么下一个线程会一直等待(不会睡眠),当上一个线程的任务执行完毕,下一个线程会立即执行。
在多 CPU 的环境中,对持有锁较短的程序来说,使用自旋锁代替一般的互斥锁往往能够提高程序的性能。

互斥锁:
当上一个线程的任务没有执行完毕的时候(被锁住),那么下一个线程会进入睡眠状态等待任务执行完毕, 当上一个线程的任务执行完毕,下一个线程会自动唤醒然后执行任务。

总结:
自旋锁会忙等: 所谓忙等,即在访问被锁资源时,调用者线程不会休眠,而是不停循环在那里,直到被锁 资源释放锁。
互斥锁会休眠: 所谓休眠,即在访问被锁资源时,调用者线程会休眠,此时 cpu 可以调度其他线程工 作。直到被锁资源释放锁。此时会唤醒休眠线程。

优缺点:
自旋锁的优点在于,因为自旋锁不会引起调用者睡眠,所以不会进行线程调度,CPU 时间片轮转等耗时操 作。所有如果能在很短的时间内获得锁,自旋锁的效率远高于互斥锁。

缺点在于,自旋锁一直占用 CPU,他在未获得锁的情况下,一直运行--自旋,所以占用着 CPU,如果不 能在很短的时 间内获得锁,这无疑会使 CPU 效率降低。自旋锁不能实现递归调用。

自旋锁:atomic、OSSpinLock、dispatch_semaphore_t
互斥锁:pthread_mutex、@ synchronized、NSLock、NSConditionLock 、NSCondition、NSRecursiveLock

锁的归类
条件锁:就是条件变量,当进程的某些资源要求不满足时就进入休眠,也就
是锁住了。当资源被分配到了,条件锁打开,进程继续运行
NSCondition
NSConditionLock

递归锁:就是同一个线程可以加锁N次而不会引发死锁
NSRecursiveLock
pthread_mutex(recursive)
信号量(semaphore):是一种更高级的同步机制,互斥锁可以说是
semaphore在仅取值0/1时的特例。信号量可以有更多的取值空间,用来实
现更加复杂的同步,而不单单是线程间互斥。
dispatch_semaphore
其实基本的锁就包括了三类 自旋锁 互斥锁 读写锁,
其他的比如条件锁,递归锁,信号量都是上层的封装和实现!

读写锁

读写锁适合于对数据结构的读次数比写次数多得多的情况. 因为, 读模式锁定时可以共享, 以写模式锁住时意味

着独占, 所以读写锁又叫共享-独占锁.

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, c***t pthread_rwlockattr_t *restrict attr);

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)

成功则返回0, 出错则返回错误编号.

同互斥量以上, 在释放读写锁占用的内存之前, 需要先通过pthread_rwlock_destroy对读写锁进行清理工作, 释

放由init分配的资源.

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

成功则返回0, 出错则返回错误编号.

这3个函数分别实现获取读锁, 获取写锁和释放锁的操作. 获取锁的两个函数是阻塞操作, 同样, 非阻塞的函数为:

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

成功则返回0, 出错则返回错误编号.

非阻塞的获取锁操作, 如果可以获取则返回0, 否则返回错误的EBUSY

iOS中的八大锁解析与使用

原子属性只对setter 或getter线程安全,在获取、赋值时添加了spinlock_t锁(os_unfair_lock)
setter底层实现

getter底层实现

OSSpinLock -- 自旋锁

*****使用

os_unfair_lock -- 互斥锁

NSLock -- 互斥锁

NSCondition -- 互斥锁 生产 -- 消费
与NSLock同样遵守NSLocking的协议,有同样的lock、unlock的api。

NSConditionLock -- 互斥锁 是基于NSCondition进一步封装,自带条件。 设置线程执行顺序

pthread_mutex -- 互斥锁
c语言实现

dispatch_semaphore 控制线程并发数

NSRecursiveLock -- 递归锁 保证同一线程下重复加锁; 在多线程环境下,递归调用会造成死锁,多线程在加锁和解锁中,会出现互相等待解锁的情况。 与NSLock一样都是基于pthread_mutex_init实现,只是设置type为递归类型。

@synchronized -- 递归锁
加锁时,在缓存获取,不会重复创建。可以在多线程下递归调用。如性能方面要求不是非常高的话,使用该锁还更简便。

读方法中的同步sync是为了栅栏函数读写互斥。 读写互斥,多读单写

死锁:当前线程在串行队列中,***同步(dispatch_sync)同一串行队列,导致线程死锁。

使用互斥锁防止静态条件的方法

1、在静态初始化之前创建互斥锁:在静态变量初始化之前创建互斥锁,可以确保在程序运行期间只有一个互斥锁实例被创建。
2、避免在静态变量初始化中使用互斥锁:如果在静态变量初始化中使用互斥锁,可能会导致死锁,因此,应该将互斥锁的初始化与静态变量分开进行。

信号量vs互斥锁(Semaphore vs Mutex)

信号量是一个被线程共享的非负变量。信号量是一个发信号的机制。一个等待一个信号量的线程可以被其他线程通知(signal)。这个机制通过 wait 和 signal 两个原子操作(atomic operati***)来实现进程同步。

一个信号量要么允许访问资源,要么不允许访问资源。二者只能选其一。而具体是哪一种,则要看设置。

详情可参考《 信号量:二进位信号量和计数信号量 》这篇文章。

互斥锁其实是一个对象。Mutex的全称是Mutual Exclusion Object,也就是互斥锁是一个互斥对象。它是一种特殊的二进位信号量(binary semaphore),用来控制访问共享区域资源。它包括一个优先级继承机制,以避免扩展的优先级反转问题。它允许当前优先级较高的任务在阻塞状态下维持的时间尽可能的少。然而,优先级继承并不能完全避免优先级反转,而只会最小化其影响。

对于单个缓冲区(single buffer),我们可以将4kb缓冲区分成四个1kb缓冲区。信号量可以与这四个缓冲区相关联。这允许用户和生产者同时处理不同的缓冲区。

互斥锁用于提供互斥,它使得拥有钥匙(key or mutex)的生产者才能访问资源。只要生产者占用了缓冲区(buffer),用户必须等待,反之亦然。在互斥锁的机制中,整块缓冲区始终只能提供给一个线程访问。

下面列举信号量的优点:

下面列举互斥锁的优点:

下面列举信号量的缺点:

下面列举互斥锁的缺点:

mutex+already+created电脑什么意思

"mutex already created" 是一个常见的错误信息,通常发生在多线程程序中。
Mutex(互斥锁)是一种用于控制多个线程访问共享资源的同步机制。当一个线程正在使用共享资源时,它会锁定这个资源,以避免其他线程同时访问。当该线程完成使用该资源后,它将解锁该资源,以允许其他线程访问。
"mutex already created" 错误通常意味着一个线程正在尝试创建一个已经存在的mutex。这可能是因为程序中的另一个线程已经创建了该mutex,或者该mutex已经在程序的某个位置被创建过了。
如果您遇到了这个错误,可以尝试以下方法解决问题:
确保mutex在需要它的地方被正确创建。在多线程程序中,确保每个线程只创建一个mutex。
确保在创建mutex之前,已经释放了所有先前创建的mutex。如果未正确释放mutex,可能会导致其他线程无法访问共享资源。
使用适当的同步机制来确保多个线程不会同时访问共享资源。这可以通过使用锁、信号量、条件变量等实现。
请注意,在多线程程序中,确保正确使用同步机制非常重要。未正确使用同步机制可能会导致竞态条件和死锁等问题,这些问题可能会导致程序崩溃或表现出不正确的行为。

[RT-Thread]互斥锁(mutex)

和 semaphore 一样, mutex 在RTT中也归类为 ipc ( ipc 应该是进程间通信,感觉命名是不是有点不贴切)。
mutex 用于资源互斥的场景,比如多个线程可能同时访问(R/W)同一个全局变量,这个时候,就需要加锁控制。

仍然主要关注 mutex控制块 、 take 和 release 操作。

parent :
和其它 ipc 方式相同,主要是维护 suspend_thread 。
value :
value其实就两个值:0或者1,1表示已被持有,0表示空闲状态。
original_priority :
保存持有该mutex的thread的本来的线程优先级,便于优先级继承后,恢复原本线程优先级。
hold :
hold 记录被同一thread请求的次数,嵌套场景。
owner :
持有该mutex的thread。

iOS线程同步(各种锁)

在iOS开发中经常会遇到一块资源被多个线程共享的情况,也就是多个线程会访问同一块资源,比如多个线程访问同一个对象、同一个变量、同一个文件,当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

使用线程同步技术(同步就是协同步调,按预定的先后顺序进行),常见的同步技术时加锁

OSSpinLock叫做”自旋锁”,等待锁的线程会处于忙等(busy-wait)状态,一直占用着CPU资源,目前已经不再安全,从iOS10已经废弃了,可能会出现优先级反转问题,如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放锁,使用需要导入头文件#import 《libkern/*****》。

os_unfair_lock用于取代不安全的OSSpinLock ,从iOS10开始才支持,从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等,使用需要导入头文件#import 《os/*****》。

mutex叫做”互斥锁”,等待锁的线程会处于休眠状态,使用需要导入头文件#import 《*****》

NSLock、NSRecursiveLock是对mutex普通锁的封装,NSLock遵守NSLocking协议

初始化锁 NSLock *lock = ;
NSRecursiveLock也是对mutex递归锁的封装,API跟NSLock基本一致

NSCondition是对mutex和cond的封装,NSCondition遵守NSLocking协议

NSCondition通常用于生产者消费者模式的业务中,当不满足条件时调用wait方法让消费者线程等待,当条件满足时调用signal方法通知消费者线程。

NSConditionLock是对NSCondition的进一步封装,可以设置具体的条件值

NSConditionLock都可以设置不同线程间的依赖,让满足条件值的线程先执行,不满足条件的线程处于等待状态。

semaphore叫做”信号量”,信号量的初始值,可以用来控制线程并发访问的最大数量,信号量的初始值为1,代表同时只允许1条线程访问资源,保证线程同步

@synchronized是对mutex递归锁的封装,源码查看:objc4中的 ***** 文件,@synchronized(obj)内部会生成obj对应的递归锁,然后进行加锁、解锁操作

性能从高到底排序

dispatch_barrier_async

dispatch_barrier_async又叫栅栏函数,这个函数传入的并发队列必须是自己通过dispatch_queue_cretate创建的,如果传入的是一个串行或是一个全局的并发队列,那这个函数便等同于dispatch_async函数的效果,使用栅栏函数可以保证同一时间只有一个线程可进行写操作,读操作可以有多少个线程进行。

linux线程同步的互斥锁(mutex)到底怎么用的》谢谢

互斥锁(mutex) 通过锁机制实现线程间的同步。

1、初始化锁。在Linux下,线程的互斥量数据类型是pthread_mutex_t。在使用前,要对它进行初始化。

2、静态分配:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

3、动态分配:int pthread_mutex_init(pthread_mutex_t *mutex, c***t pthread_mutex_attr_t *mutexattr);

4、加锁。对共享资源的访问,要对互斥量进行加锁,如果互斥量已经上了锁,调用线程会阻塞,直到互斥量被解锁。

    int pthread_mutex_lock(pthread_mutex *mutex);
    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    解锁。在完成了对共享资源的访问后,要对互斥量进行解锁。
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    销毁锁。锁在是使用完成后,需要进行销毁以释放资源。
    int pthread_mutex_destroy(pthread_mutex *mutex);
    #include 《cstdio》  
    #include 《cstdlib》  
    #include 《*****》  
    #include 《*****》  
    #include "iostream"  
    using namespace std;  
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  
    int tmp;  
    void* thread(void *arg)  
    {  
        cout 《《 "thread id is " 《《 pthread_self() 《《 endl;  
        pthread_mutex_lock(&mutex);  
        tmp = 12;  
        cout 《《 "Now a is " 《《 tmp 《《 endl;  
        pthread_mutex_unlock(&mutex);  
        return NULL;  
    }  
    int main()  
    {  
        pthread_t id;  
        cout 《《 "main thread id is " 《《 pthread_self() 《《 endl;  
        tmp = 3;  
        cout 《《 "In main func tmp = " 《《 tmp 《《 endl;  
        if (!pthread_create(&id, NULL, thread, NULL))  
        {  
            cout 《《 "Create thread success!" 《《 endl;  
        }  
        else  
        {  
            cout 《《 "Create thread failed!" 《《 endl;  
        }  
        pthread_join(id, NULL);  
        pthread_mutex_destroy(&mutex);  
        return 0;  
    }  
    //编译:g++ -o thread ***** -lpthread

Linux 之mutex 源码分析

 mutex相关的函数并不是linux kernel实现的,而是glibc实现的,源码位于nptl目录下。

***隐藏网址***
首先说数据结构:

typedef union

{

  struct

  {

    int __lock;

    unsigned int __count;

    int __owner;

    unsigned int __nusers;

    /* KIND must stay at this position in the structure to maintain

       binary compatibility.  */

    int __kind;

    int __spins;

  } __data;

  char __size;

  long int __align;

} pthread_mutex_t;
 int __lock;  资源竞争引用计数

 int __kind; 锁类型,init 函数中mutexattr 参数传递,该参数可以为NULL,一般为 PTHREAD_MUTEX_NORMAL

结构体其他元素暂时不了解,以后更新。
/*nptl/pthread_mutex_******/

int

__pthread_mutex_init (mutex, mutexattr)

     pthread_mutex_t *mutex;

     c***t pthread_mutexattr_t *mutexattr;

{

  c***t struct pthread_mutexattr *imutexattr;
  assert (sizeof (pthread_mutex_t) 《= __SIZEOF_PTHREAD_MUTEX_T);
  imutexattr = (c***t struct pthread_mutexattr *) mutexattr ?: &default_attr;
  /* Clear the whole variable.  */

  memset (mutex, ’\0’, __SIZEOF_PTHREAD_MUTEX_T);
  /* Copy the values from the attribute.  */

  mutex-》__data.__kind = imutexattr-》mutexkind & ~0x80000000;
  /* Default values: mutex not used yet.  */

  // mutex-》__count = 0;        already done by memset

  // mutex-》__owner = 0;        already done by memset

  // mutex-》__nusers = 0;        already done by memset

  // mutex-》__spins = 0;        already done by memset
  return 0;

}
init函数就比较简单了,将mutex结构体清零,设置结构体中__kind属性。
/*nptl/pthread_mutex_******/

int

__pthread_mutex_lock (mutex)

     pthread_mutex_t *mutex;

{

  assert (sizeof (mutex-》__size) 》= sizeof (mutex-》__data));
  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
  switch (__builtin_expect (mutex-》__data.__kind, PTHREAD_MUTEX_TIMED_NP))

    {

     …

    default:

      /* Correct code cannot set any other type.  */

    case PTHREAD_MUTEX_TIMED_NP:

    ******:

      /* Normal mutex.  */

      LLL_MUTEX_LOCK (mutex-》__data.__lock);

      break;
  …

  }
  /* Record the ownership.  */

  assert (mutex-》__data.__owner == 0);

  mutex-》__data.__owner = id;

#ifndef NO_INCR

  ++mutex-》__data.__nusers;

#endif
  return 0;

}

该函数主要是调用LLL_MUTEX_LOCK, 省略部分为根据mutex结构体__kind属性不同值做些处理。

宏定义函数LLL_MUTEX_LOCK最终调用,将结构体mutex的__lock属性作为参数传递进来

#define __lll_mutex_lock(futex)                                                \

  ((void) ({                                                                \

    int *__futex = (futex);                                                \

    if (atomic_compare_and_exchange_bool_acq (__futex, 1, 0) != 0)        \

      __lll_lock_wait (__futex);                                        \

  }))
atomic_compare_and_exchange_bool_acq (__futex, 1, 0)宏定义为:

#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \

  ({ __typeof (mem) __gmemp = (mem);                                      \

     __typeof (*mem) __gnewval = (newval);                              \

      \

     *__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; })
这个宏实现的功能是:

如果mem的值等于oldval,则把newval赋值给mem,放回0,否则不做任何处理,返回1.

由此可以看出,当mutex锁限制的资源没有竞争时,__lock 属性被置为1,并返回0,不会调用__lll_lock_wait (__futex); 当存在竞争时,再次调用lock函数,该宏不做任何处理,返回1,调用__lll_lock_wait (__futex);
void

__lll_lock_wait (int *futex)

{

  do

    {

      int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);

      if (oldval != 0)

lll_futex_wait (futex, 2);

    }

  while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);

}
atomic_compare_and_exchange_val_acq (futex, 2, 1); 宏定义:

/* The only basic operation needed is compare and exchange.  */

#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \

  ({ __typeof (mem) __gmemp = (mem);                                      \

     __typeof (*mem) __gret = *__gmemp;                                      \

     __typeof (*mem) __gnewval = (newval);                              \

      \

     if (__gret == (oldval))                                              \

       *__gmemp = __gnewval;                                              \

     __gret; })

这个宏实现的功能是,当mem等于oldval时,将mem置为newval,始终返回mem原始值。

此时,futex等于1,futex将被置为2,并且返回1. 进而调用

lll_futex_wait (futex, 2);

#define lll_futex_timed_wait(ftx, val, timespec)                        \

({                                                                        \

   DO_INLINE_SYSCALL(futex, 4, (long) (ftx), FUTEX_WAIT, (int) (val),        \

     (long) (timespec));                                \

   _r10 == -1 ? -_retval : _retval;                                        \

})

该宏对于不同的平台架构会用不同的实现,采用汇编语言实现系统调用。不过确定的是调用了Linux kernel的futex系统调用。

futex在linux kernel的实现位于:kernel/*****

SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,

struct timespec __user *, utime, u32 __user *, uaddr2,

u32, val3)

{

struct timespec ts;

ktime_t t, *tp = NULL;

u32 val2 = 0;

int cmd = op & FUTEX_CMD_MASK;
if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||

      cmd == FUTEX_WAIT_BITSET ||

      cmd == FUTEX_WAIT_REQUEUE_PI)) {

if (copy_from_user(&ts, utime, sizeof(ts)) != 0)

return -EFAULT;

if (!timespec_valid(&ts))

return -EINVAL;
t = timespec_to_ktime(ts);

if (cmd == FUTEX_WAIT)

t = ktime_add_safe(ktime_get(), t);

tp = &t

}

/*

 * requeue parameter in ’utime’ if cmd == FUTEX_*_REQUEUE_*.

 * number of waiters to wake in ’utime’ if cmd == FUTEX_WAKE_OP.

 */

if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE ||

    cmd == FUTEX_CMP_REQUEUE_PI || cmd == FUTEX_WAKE_OP)

val2 = (u32) (unsigned long) utime;
return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);

}

futex具有六个形参,pthread_mutex_lock最终只关注了前四个。futex函数对参数进行判断和转化之后,直接调用do_futex。

long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,

u32 __user *uaddr2, u32 val2, u32 val3)

{

int clockrt, ret = -ENOSYS;

int cmd = op & FUTEX_CMD_MASK;

int fshared = 0;
if (!(op & FUTEX_PRIVATE_FLAG))

fshared = 1;
clockrt = op & FUTEX_CLOCK_REALTIME;

if (clockrt && cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI)

return -ENOSYS;
switch (cmd) {

case FUTEX_WAIT:

val3 = FUTEX_BITSET_MATCH_ANY;

case FUTEX_WAIT_BITSET:

ret = futex_wait(uaddr, fshared, val, timeout, val3, clockrt);

break;

         …

default:

ret = -ENOSYS;

}

return ret;

}

省略部分为对其他cmd的处理,pthread_mutex_lock函数最终传入的cmd参数为FUTEX_WAIT,所以在此只关注此分之,分析futex_wait函数的实现。

static int futex_wait(u32 __user *uaddr, int fshared,

      u32 val, ktime_t *abs_time, u32 bitset, int clockrt)

{

struct hrtimer_sleeper timeout, *to = NULL;

struct restart_block *restart;

struct futex_hash_bucket *hb;

struct futex_q q;

int ret;
           … … //delete parameters check and convertion

retry:

/* Prepare to wait on uaddr. */

ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);

if (ret)

goto out;
/* queue_me and wait for wakeup, timeout, or a signal. */

futex_wait_queue_me(hb, &q, to);

… … //other handlers

return ret;

}

futex_wait_setup 将线程放进休眠队列中,

futex_wait_queue_me(hb, &q, to);将本线程休眠,等待唤醒。
唤醒后,__lll_lock_wait函数中的while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); 语句将被执行,由于此时futex在pthread_mutex_unlock中置为0,所以atomic_compare_and_exchange_bool_acq (futex, 2, 0)语句将futex置为2,返回0. 退出循环,访问用户控件的临界资源。
/*nptl/pthread_mutex_******/

int

internal_function attribute_hidden

__pthread_mutex_unlock_usercnt (mutex, decr)

     pthread_mutex_t *mutex;

     int decr;

{

  switch (__builtin_expect (mutex-》__data.__kind, PTHREAD_MUTEX_TIMED_NP))

    {

   … …

    default:

      /* Correct code cannot set any other type.  */

    case PTHREAD_MUTEX_TIMED_NP:

    case PTHREAD_MUTEX_ADAPTIVE_NP:

      /* Normal mutex.  Nothing special to do.  */

      break;

    }
  /* Always reset the owner field.  */

  mutex-》__data.__owner = 0;

  if (decr)

    /* One less user.  */

    --mutex-》__data.__nusers;
  /* Unlock.  */

  lll_mutex_unlock (mutex-》__data.__lock);
  return 0;

}

省略部分是针对不同的__kind属性值做的一些处理,最终调用 lll_mutex_unlock。

该宏函数最终的定义为:

#define __lll_mutex_unlock(futex)                        \

  ((void) ({                                                \

    int *__futex = (futex);                                \

    int __val = atomic_exchange_rel (__futex, 0);        \

\

    if (__builtin_expect (__val 》 1, 0))                \

      lll_futex_wake (__futex, 1);                        \

  }))

atomic_exchange_rel (__futex, 0);宏为:

#define atomic_exchange_rel(mem, value) \

  (__sync_synchronize (), __sync_lock_test_and_set (mem, value))

实现功能为:将mem设置为value,返回原始mem值。

__builtin_expect (__val 》 1, 0) 是编译器优化语句,告诉编译器期望值,也就是大多数情况下__val 》 1 ?是0,其逻辑判断依然为if(__val 》 1)为真的话执行 lll_futex_wake。

现在分析,在资源没有被竞争的情况下,__futex 为1,那么返回值__val则为1,那么 lll_futex_wake (__futex, 1);        不会被执行,不产生系统调用。 当资源产生竞争的情况时,根据对pthread_mutex_lock 函数的分析,__futex为2, __val则为2,执行 lll_futex_wake (__futex, 1); 从而唤醒等在临界资源的线程。

lll_futex_wake (__futex, 1); 最终会调动同一个系统调用,即futex, 只是传递的cmd参数为FUTEX_WAKE。

在linux kernel的futex实现中,调用

static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)

{

struct futex_hash_bucket *hb;

struct futex_q *this, *next;

struct plist_head *head;

union futex_key key = FUTEX_KEY_INIT;

int ret;
if (!bitset)

return -EINVAL;
ret = get_futex_key(uaddr, fshared, &key);

if (unlikely(ret != 0))

goto out;
hb = hash_futex(&key);

spin_lock(&hb-》lock);

head = &hb-》chain;
plist_for_each_entry_safe(this, next, head, list) {

if (match_futex (&this-》key, &key)) {

if (this-》pi_state || this-》rt_waiter) {

ret = -EINVAL;

break;

}
/* Check if one of the bits is set in both bitsets */

if (!(this-》bitset & bitset))

continue;
wake_futex(this);

if (++ret 》= nr_wake)

break;

}

}
spin_unlock(&hb-》lock);

put_futex_key(fshared, &key);

out:

return ret;

}

该函数遍历在该mutex上休眠的所有线程,调用wake_futex进行唤醒,

static void wake_futex(struct futex_q *q)

{

struct task_struct *p = q-》task;
/*

 * We set q-》lock_ptr = NULL _before_ we wake up the task. If

 * a non futex wake up happens on another CPU then the task

 * might exit and p would dereference a non existing task

 * struct. Prevent this by holding a reference on p across the

 * wake up.

 */

get_task_struct(p);
plist_del(&q-》list, &q-》*****);

/*

 * The waiting task can **** the futex_q as soon as

 * q-》lock_ptr = NULL is written, without taking any locks. A

 * memory barrier is required here to prevent the following

 * store to lock_ptr from getting ahead of the plist_del.

 */

**p_wmb();

q-》lock_ptr = NULL;
wake_up_state(p, TASK_NORMAL);

put_task_struct(p);

}

wake_up_state(p, TASK_NORMAL);  的实现位于kernel/*****中,属于linux进程调度的技术。

有关mutex锁自旋锁与互斥锁,我们就先探讨这些。如果你有独特的经验或问题,期待在下方看到你的声音。
本文编辑:admin

更多文章:


today()函数的使用方法(Excel中today函数的使用方法及日期计算应用)

today()函数的使用方法(Excel中today函数的使用方法及日期计算应用)

本文是您理解today()函数的使用方法的最后一站。我们将通过剖析Excel中today函数的使用方法及日期计算应用,帮你打通任督二脉,彻底领悟。

2026年5月4日 21:00

typedef enum和enum详细用法(C语言笔记(五)----struct,enum,typedef等)

typedef enum和enum详细用法(C语言笔记(五)----struct,enum,typedef等)

想高效掌握typedef enum和enum详细用法的核心吗?本文将为你聚焦C语言笔记(五)----struct,enum,typedef等这一关键环节,帮你节省大量摸索时间。

2026年5月4日 20:40

spill over into(急死了!!英文好的请进来帮帮忙啊)

spill over into(急死了!!英文好的请进来帮帮忙啊)

各位老铁们好,相信很多人对spill over into都不是特别的了解,因此呢,今天就来为大家分享下关于spill over into以及急死了!!英文好的请进来帮帮忙啊的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!

2026年5月4日 20:20

学做网站论坛(怎样才能做网站)

学做网站论坛(怎样才能做网站)

各位朋友,关于学做网站论坛的讨论一直很多,今天咱们不聊复杂的,就聚焦于怎样才能做网站,用最直白的方式把它讲清楚。

2026年5月4日 20:00

多层json的解析(如何用Python解析多层嵌套的JSON)

多层json的解析(如何用Python解析多层嵌套的JSON)

想快速搞懂多层json的解析吗?本文将围绕如何用Python解析多层嵌套的JSON等核心问题,用最直白的语言为您提供一份实用指南,帮您节省大量摸索的时间。

2026年5月4日 19:40

css链接样式有几种(CSS设置链接的样式)

css链接样式有几种(CSS设置链接的样式)

曾几何时,我也觉得css链接样式有几种高不可攀,尤其CSS设置链接的样式更是一头雾水。后来才发现,只是没找对方法,希望我的经验能帮到你。

2026年5月4日 19:20

opengl+和directx+哪个好(OpenGL跟Direct**哪个比较好)

opengl+和directx+哪个好(OpenGL跟Direct**哪个比较好)

花费5分钟阅读本文,您将获得对opengl+和directx+哪个好和OpenGL跟Direct**哪个比较好的清晰认知,远超自己搜索数小时的效果。

2026年5月4日 19:00

json文件怎么编写(macbook air怎么创建json文件)

json文件怎么编写(macbook air怎么创建json文件)

有研究表明,成功掌握json文件怎么编写的学习者,普遍在macbook air怎么创建json文件这个环节投入了更多精力。其重要性不言而喻。

2026年5月4日 18:40

ui设计好找工作吗?(UI设计现状怎么样,好找工作吗)

ui设计好找工作吗?(UI设计现状怎么样,好找工作吗)

很多朋友初次接触ui设计好找工作吗?可能会觉得有点陌生,这很正常。今天这篇文章,咱们就一起把UI设计现状怎么样,好找工作吗这事儿聊透,希望能帮您理清思路。

2026年5月4日 18:20

python可以做软件吗(python能写软件吗)

python可以做软件吗(python能写软件吗)

老铁们,关于python可以做软件吗,你可能听过不少说法。今天,咱们就坐下来好好聊聊python能写软件吗,保证让你豁然开朗。

2026年5月4日 18:00

最近更新

学做网站论坛(怎样才能做网站)
2026-05-04 20:00:01 浏览:0
opengl+和directx+哪个好(OpenGL跟Direct**哪个比较好)
2026-05-04 19:00:01 浏览:0
热门文章

split函数 sql(求sql split函数的用法)
2026-03-26 20:40:01 浏览:1
标签列表