当前位置:首页 » 文件传输 » 使用互斥锁保护内存的访问
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

使用互斥锁保护内存的访问

发布时间: 2023-04-09 01:31:22

❶ 互斥锁,自旋锁,原子操作原理和实现

注意:互斥锁在上锁的过程中,需要用自旋锁保证原子操作(包括修改原子量和锁的相关数据结构)

自旋锁是采用忙等的状态获取锁,所以会一直占用cpu资源,但是允许不关闭中断的情况下,是可以被其他内核执行路径抢占的(中断嵌套的尘纳情况下,注意嵌套的中断不能申请同一个锁,这样会造成死等)。同时因为线程对cpu一直保持占用状态,所以对小资源加锁效率比较高,不需要做任何的线程切换,一般情况下如果加锁资源的运行延迟小于线程或者进程切换的时延则推荐使用自旋锁。如果需要等待耗时操作,则建议胡激放弃cpu,采用信号量或者互斥锁

上图指令可以实现加操作的原子性,但是这种总线锁不能滥用,在没有共享同步问题的时候,这会阻止cpu并行计算的优化,甚至会阻塞cpu对其他内存的访问,导致裤兄袜效率的下降。所以除此之外我们可以使用缓存锁来执行复杂的原子操作。

频繁使用的内存会缓存在处理器的L1、L2和L3高速缓存里,那么原子操作就可以直接在处理器内部缓存中进行,并不需要声明总线锁,在Pentium 6和目前的处理器中可以使用“缓存锁定”的方式来实现复杂的原子性。 所谓“缓存锁定”是指内存区域如果被缓存在处理器的缓存行中,并且在Lock操作期间被锁定,那么当它执行锁操作回写到内存时,处理器不在总线上声言LOCK#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子性,因为缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据,当其他处理器回写已被锁定的缓存行的数据时,会使缓存行无效,在如图2-3所示的例子中,当CPU1修改缓存行中的i时使用了缓存锁定,那么CPU2就不能同时缓存i的缓存行。
但是有两种情况下处理器不会使用缓存锁定。

未完待续。。。。

https://www.cnblogs.com/alinh/p/6905221.html
https://blog.csdn.net/mcgrady_tracy/article/details/34829019
https://leetcode.com/discuss/interview-question/operating-system/125169/Mutex-vs-Semaphore
https://blog.csdn.net/zxx901221/article/details/83033998
https://leetcode.com/discuss/interview-question/operating-system/134290/Implement-your-own-spinlock

❷ 信号量,互斥锁,读写锁和条件变量的区别

信号量强调的是线程(或进程)间的同步:“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都 在sem_wait的时候,就阻塞在那里)。当信号量为单值信号量是,也可以完成一个资源的互斥访问。

有名信号量:可以用于不同进程间或多线程间的互斥与同步
创建打开有名信号量
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

成功返回信号量指针;失败返回SEM_FAILED,设置errnoname是文件路察旅径名,但不能写成/tmp/a.sem这样的形式,因为在linux下,sem都是在/dev/shm目录下,可写成"/mysem"或"mysem",创建出来的文件都 是"/dev/shm/sem.mysem",mode设置为0666,value设置为信号量的初始值.所需信号灯等已存在条件下指定O_CREAT|O_EXCL却是个错误。

关闭信号量,进程终止时,会自动调用它
int sem_close(sem_t *sem);
成功返回0;失败返回-1,设置errno

删除信号量,立即删除信号量名字,当其他进程都关闭它时,销毁它
int sem_unlink(const char *name);

等待信号量,测试信号量的值,如果其值小于或等于0,那么就等待(阻塞);一旦其值变为大于0就将它减1,并返回
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);

成功返回0;失败返回-1,设置errno

当信号量的值为0时,sem_trywait立即返回,设置errno为EAGAIN。如果被某个信号中断,sem_wait会过早地返回,设置errno为EINTR

发出信号量,给它的值加1,然后唤醒正在等待该信号量的进程或线程
int sem_post(sem_t *sem);

成功返回0;失败返回-1,不会改变它的值,设滑埋置errno,该函数是异步信号安全的,可以在信号处理程序里调用它无名信号量,用于进程体内各线程间的互斥和同步,使用如下API(无名信号量,基于内存的信号量)

(1)、sem_init

功能:用于创建一个信号量,并初始化信号量的值。

头文件:

函数原型: int sem_init (sem_t* sem, int pshared, unsigned int value);

函数传败让凳入值: sem:信号量。pshared:决定信号量能否在几个进程间共享。由于目前LINUX还没有实现进程间共享信息量,所以这个值只能取0。

(2)其他函数。
int sem_wait (sem_t* sem);
int sem_trywait (sem_t* sem);
int sem_post (sem_t* sem);
int sem_getvalue (sem_t* sem);
int sem_destroy (sem_t* sem);

功能:sem_wait和sem_trywait相当于P操作,它们都能将信号量的值减一,两者的区别在于若信号量的值小于零时,sem_wait将会阻塞进程,而sem_trywait则会立即返回。sem_post相当于V操作,它将信号量的值加一,同时发出唤醒的信号给等待的进程(或线程)。

sem_getvalue 得到信号量的值。

sem_destroy 摧毁信号量。

如果某个基于内存的信号灯是在不同进程间同步的,该信号灯必须存放在共享内存区中,这要只要该共享内存区存在,该信号灯就存在。

互斥锁(又名互斥量)强调的是资源的访问互斥:互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源。比如对全局变量的访问,有时要加锁,操作完了,在解锁。有的时候锁和信号量会同时使用的”

也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务并不一定是锁定某一资源,还可以是进行一些计算或者数据处理之类。而线程互斥量则是“锁住某一资源”的概念,在锁定期间内,其他线程无法对被保护的数据进行操作。在有些情况下两者可以互换。

在linux下, 线程的互斥量数据类型是pthread_mutex_t. 在使用前, 要对它进行初始化:

对于静态分配的互斥量, 可以把它设置为PTHREAD_MUTEX_INITIALIZER, 或者调用pthread_mutex_init.

对于动态分配的互斥量, 在申请内存(malloc)之后, 通过pthread_mutex_init进行初始化, 并且在释放内存(free)前需要调用pthread_mutex_destroy.
原型:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

头文件:

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

说明: 如果使用默认的属性初始化互斥量, 只需把attr设为NULL. 其他值在以后讲解.

首先说一下加锁函数:

头文件:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);

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

说 明: 具体说一下trylock函数, 这个函数是非阻塞调用模式, 也就是说, 如果互斥量没被锁住, trylock函数将把互斥量加锁, 并获得对共享资源的访问权限; 如果互斥量 被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态.

再说一下解所函数:

头文件:
原型: int pthread_mutex_unlock(pthread_mutex_t *mutex);

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

条件变量常与互斥锁同时使用,达到线程同步的目的:条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足。在发 送信号时,如果没有线程 等待在该条件变量上,那么信号将丢失;而信号量有计数值,每次信号量post操作都会被记录

1. 互斥锁必须是谁上锁就由谁来解锁,而信号量的wait和post操作不必由同一个线程执行。

2. 互斥锁要么被锁住,要么被解开,和二值信号量类似

3. sem_post是各种同步技巧中,唯一一个能在信号处理程序中安全调用的函数

4. 互斥锁是为上锁而优化的;条件变量是为等待而优化的; 信号量既可用于上锁,也可用于等待,因此会有更多的开销和更高的复杂性

5. 互斥锁,条件变量都只用于同一个进程的各线程间,而信号量(有名信号量)可用于不同进程间的同步。当信号量用于进程间同步时,要求信号量建立在共享内存区。

6. 信号量有计数值,每次信号量post操作都会被记录,而条件变量在发送信号时,如果没有线程在等待该条件变量,那么信号将丢失。

读写锁

读写锁与互斥量类似,不过读写锁允许更高的并行性。互斥量要么是锁住状态要么是不加锁状态,而且一次只有一个线程可以对其加锁。

读写锁可以由三种状态:读模式下加锁状态、写模式下加锁状态、不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写
锁。

在读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是如果线程希望以写模式对此锁进行加锁,它必须阻塞直到所有的线程释放读锁。虽然读写锁的实现各不相同,但当读写锁处于读模式锁住状态时,如果有另外的线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求。这样可以避免读模式锁长期占用,而等待的写模式锁请求一直得不到满足。

读写锁非常适合于对数据结构读的次数远大于写的情况。当读写锁在写模式下时,它所保护的数据结构就可以被安全地修改,因为当前只有一个线程可以在写模式下拥 有这个锁。当读写锁在读状态下时,只要线程获取了读模式下的读写锁,该锁所保护的数据结构可以被多个获得读模式锁的线程读取。

读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的;当他以写模式锁住时,它是以独占模式锁住的。
初始化和销毁:
#include
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

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

同互斥量以上, 在释放读写锁占用的内存之前, 需要先通过thread_rwlock_destroy对读写锁进行清理工作, 释放由init分配的资源.

读和写:
#include
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个函数分别实现获取读锁, 获取写锁和释放锁的操作. 获取锁的两个函数是阻塞操作, 同样, 非阻塞的函数为:
#include
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

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

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

虽然读写锁提高了并行性,但是就速度而言并不比互斥量快.

可能这也是即使有读写锁存在还会使用互斥量的原因,因为他在速度方面略胜一筹。这就需要我们在写程序的时候综合考虑速度和并行性并找到一个折中。

比如: 假设使用互斥量需要0.5秒,使用读写锁需要0.8秒。在类似学生管理系统这类软件中,可能百分之九十的时间都是查询操作,那么假如现在突然来个个20个请求,如果使用的是互斥量,那么最后的那个查询请求被满足需要10后。这样,估计没人能受得了。而使用读写锁,应为 读锁能够多次获得。所以所有的20个请求,每个请求都能在1秒左右得到满足。

也就是说,在一些写操作比较多或是本身需要同步的地方并不多的程序中我们应该使用互斥量,而在读操作远大于写操作的一些程序中我们应该使用读写锁来进行同步

条件变量(condition)

条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。

条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,其它线程在获得互斥量之前不会察觉到这种改变,因此必须锁定互斥量以后才能计算条件。

条件的检测是在互斥锁的保护下进行的。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件

变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量可以被用来实现这两进程间的线程同步。

1. 初始化:

条件变量采用的数据类型是pthread_cond_t, 在使用之前必须要进行初始化, 这包括两种方式:

静态: 可以把常量PTHREAD_COND_INITIALIZER给静态分配的条件变量.
动态: pthread_cond_init函数, 是释放动态条件变量的内存空间之前, 要用pthread_cond_destroy对其进行清理.
#include
int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);

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

注意:条件变量占用的空间并未被释放。

当pthread_cond_init的attr参数为NULL时, 会创建一个默认属性的条件变量; 非默认情况以后讨论.

2. 等待条件:
#include
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);

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

这两个函数分别是阻塞等待和超时等待.

等待条件函数等待条件变为真, 传递给pthread_cond_wait的互斥量对条件进行保护, 调用者把锁住的互斥量传递给函数. 函数把调用线程放到等待条件的线程列表上, 然后对互斥量解锁, 这两个操作是原子的. 这样 便关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道, 这样线程就不会错过条件的任何变化.

当pthread_cond_wait返回时, 互斥量再次被锁住.

pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,必须重新检查条件的值。

pthread_cond_wait函数返回时,相应的互斥锁将被当前线程锁定,即使是函数出错返回。

阻塞在条件变量上的线程被唤醒以后,直到pthread_cond_wait()函数返回之前条件的值都有可能发生变化。所以函数返回以后,在锁定相应的互斥锁之前,必须重新测试条 件值。最好的测试方法是循环调用pthread_cond_wait函数,并把满足条件的表达式置为循环的终止条件。如:

pthread_mutex_lock();

while (condition_is_false)

pthread_cond_wait();

pthread_mutex_unlock();

阻塞在同一个条件变量上的不同线程被释放的次序是不一定的。

注意:pthread_cond_wait()函数是退出点,如果在调用这个函数时,已有一个挂起的退出请求,且线程允许退出,这个线程将被终止并开始执行善后处理函数,而这时和条 件变量相关的互斥锁仍将处在锁定状态。

pthread_cond_timedwait函数到了一定的时间,即使条件未发生也会解除阻塞。这个时间由参数abstime指定。函数返回时,相应的互斥锁往往是锁定的,即使是函数出错返回。

注意:pthread_cond_timedwait函数也是退出点。

超时时间参数是指一天中的某个时刻。使用举例:

pthread_timestruc_t to;

to.tv_sec = time(NULL) + TIMEOUT;

to.tv_nsec = 0;

超时返回的错误码是ETIMEDOUT。

3. 通知条件:
#include
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

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

这两个函数用于通知线程条件已经满足. 调用这两个函数, 也称向线程或条件发送信号. 必须注意, 一定要在改变条件状态以后再给线程发送信号.

❸ 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, const pthread_mutex_attr_t *mutexattr);

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

intpthread_mutex_lock(pthread_mutex*mutex);
intpthread_mutex_trylock(pthread_mutex_t*mutex);
解锁。在完成了对共享资源的访问后,要对互斥量进行解锁。
intpthread_mutex_unlock(pthread_mutex_t*mutex);
销毁锁。锁在是使用完成后,需要进行销毁以释放资源。
intpthread_mutex_destroy(pthread_mutex*mutex);
#include<cstdio>
#include<cstdlib>
#include<unistd.h>
#include<pthread.h>
#include"iostream"
薯卖usingnamespacestd;
pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;
inttmp;
void*thread(void*arg)
{
cout<<"threadidis"<<pthread_self()<<endl;
pthread_mutex_lock(&mutex);
tmp=12;
cout<<"Nowais"<<tmp<<endl;
pthread_mutex_unlock(&mutex);
returnNULL;
}
intmain()
{
pthread_tid;
cout<<"mainthreadidis"<<pthread_self()<<endl;
tmp=3;
cout<<"Inmainfunctmp="<<tmp<<endl;
if(!pthread_create(&id,NULL,thread,NULL))
{
cout<<"Createthreadsuccess!"<<endl;
}
else
{
cout<<"Createthreadfailed!"<<endl;
}
pthread_join(id,NULL);
pthread_mutex_destroy(&mutex);
return0;
}
//编译:g++-othreadtestthread.cpp-lpthread

❹ 自旋锁与互斥锁

自旋锁:
是一种用于保护多线程共享资源的锁,与一般互斥锁(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, const 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

❺ 如何保护静态变量

保护静态变量的方法有使用互喊唤行斥锁,使用原子变量,使用局部静链耐态变量。
1、使用互斥锁:在访问静态变量前加锁,执行完后释放锁,确保同一时间只有一个线程可以访问该变量。
2、使用原子变量:原子变量可郑哗以保证自增、自减等操作的原子性,从而避免数据竞争。
3、使用局部静态变量:将静态变量放在函数内部作为局部静态变量,可以避免多个线程同时访问和修改该变量的问题。

❻ 线程同步互斥锁和读写锁的区别和各自适用场景

线程同步的方式包括:互斥锁、读写锁、条件变量、信号量和令牌。互斥锁和读写锁:提供对临界资源的保护,当多线程试图访问临界资源时,都必须通过获取锁的方式来访问临界资源。(临界资源:是被多线程共享的资源)当读写线程获取锁的频率差别不销物桐大时,一般采用互斥锁,如果读线程访问临界资源的频率大于写线程,这个时候采用读写锁较为合适,读写锁允许多个读线程同时亏坦访问临界资源,读写线程必须互斥访问临界资源。读写锁的实现蚂洞采用了互斥锁,所以在读写次数差不多的情况下采用读写锁性能没有直接采用互斥锁来的高。

❼ Linux中 条件变量为什么要用互斥锁来保护

你不管他是条件变量还是其他什么变量。只要理解,因为这个变量/资源是共享的,可能会有多个进程或线程去修改它,那么就必须为它添加一个锁,这个锁是每次只有一个进程/线程可以获取到的。
打个比方,
mutex是一个布尔型变量,表示这个答宴资源变量(锁)的一个钥匙。
为真的是时候表示这个钥匙当前是可以借,
反之为假的时候表示已经有线程山歼在使用这个钥匙。
在Java里边就用关键字synchronized来指定一个代码块一次只有一个线程可以访问。
取钥匙这个函数/方法的算法就可以这么理解了:如果这个锁可借,那么返回真,表示可借;否则返回假表示不可借
public
synchronized
boolean
getmutex(){//取钥匙
if(mutex==true)//钥匙空闲可用
{
mutex=false;//取钥匙就进行修改,证明这一次取钥匙已经发生
return
true;//返回真,表示取钥匙成功
}
else
return
false;//这个钥匙正在被使用,返回假表示去钥匙失败
}
就像一个公用电话亭,这就相当于规定了一次只允许一个人进门,你进去了就把门关上。门关着其他人就进不去了,只清唯银有你打完电话出来开门,释放这个锁,其他人才可以进去。
通过synchronized关键字将取钥匙跟进门两个动作放在在一起,绑在一块。
其中门就是条件变量,mutex就是这个门的互斥锁。