Lock()是怎么实现的

在并发编程中,经常会申请一块代码去加锁操作,比如new Reentrantlock().lock();

需求一:假设我们有十个线程t1-t10同时到达临界区,只有一个线程能获取锁,其余线程只能等待其释放锁才有机会去获得锁。

对于这么一个需求,如果是你该如何去设计lock()这个方法来满足以上需求?

1.设计一个状态 volatile state = 0;

2.当第一个线程调用lock方法,那么立马设置state值为1,表示获取了锁;如果当前线程再次获取锁也就是重入锁,那么state++;

大致思路  if(cas(state,1));如果成功则表示获得锁,假设t1获得锁,不会被阻塞,直接进入临界区。

3.其他线程调用lock方法,发现state已经被人修改不为0,那么放弃获取锁,把自己丢到一个等待队列里面,等待别人唤醒自己;

其他线程同样判断 if(cas(state,1));只要t1没有释放,state不为0,判断结果肯定是false,那么进入到等待队列。

需求二:线程1结束了任务释放锁,那么如何去通知其他线程?

其实这里又出现两种情况,公平锁与非公平锁。如果是公平锁那么一旦线程1任务结束,将会去唤醒等待队列里等待最久的元素,也就是

需要先进先出队列来满足这种需求。如果是非公平锁,那么会出现插队的情况产生,也就是任务1刚好结束的时候又来个一个线程11,该线程

会调用cas(state,1),恰好成功(其实几率很小),那么11线程就会优先于等待中的9个线程先执行

 

时间: 2024-11-10 12:06:17

Lock()是怎么实现的的相关文章

Java并发(2):Lock

在上一篇文章中我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式来实现同步访问,那就是Lock. 也许有朋友会问,既然都可以通过synchronized来实现同步访问了,那么为什么还需要提供Lock?这个问题将在下面进行阐述.本文先从synchronized的缺陷讲起,然后再讲述java.util.concurrent.locks包下常用的有哪些类和接口,最后

C# 多线程 lock 实例

class Program { static void Main(string[] args) { //在t1线程中调用LockMe,并将deadlock设为true(将出现死锁) int i = 10; while (i > 0) {  Thread t1 = new Thread(LockMe); t1.Start(true); Thread.Sleep(1000);  Console.WriteLine(string.Format("1.i:{0},开始调用LockMe :{1}&q

mysql启动报错:Fatal error: Can’t open and lock privilege tables: Table ‘mysql.host’ doesn’t exist

mysql在首次启动的时候可能会报错:Can’t open and lock privilege tables: Table ‘mysql.host’ doesn’t exist 这时候可以执行脚本 mysql_install_db –user=mysql –ldata=数据存放的路径

MySQL5.6.12 Waiting for commit lock导致从库hang住的问题剖析

nagios报警,线上一台从库检测不到slave状态,于是远程上去查看问题: 1,show slave status\G卡住: Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show slave status\G show slave status卡住了,动弹不了,这种情况还是第一次遇到. 2,看w负载无压力: [root@tmp3_72 ~]# w 13:23:31 u

Ubuntu15、Ubuntu14交换Ctrl和Caps Lock键

在Ubuntu12.04中,交换Ctrl和Caps Lock键非常简单,直接图形就可以设置,但是到了Ubuntu14之后居然没有了,只能去使用命令来设置了. setxkbmap -option ctrl:swapcaps 在终端输入如上命令就可以实现了,但是这样重启后就没有效果了. 在/etc/rc.local最后增加上这句话,重启后没有生效: 在/etc/profile最后中增加上这句话,重启后没有生效: 在/etc/bash.bashrc最后中增加这句话,重启后生效.

mysql Lock wait timeout exceeded

MySQL 事务没有提交导致 锁等待 Lock wait timeout exceeded java.lang.Exception:### Error updating database.  Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction### The error may involve defaultParameterMap### The error occurred wh

Java多线程之~~~Lock接口和ReentrantLock的使用

在多线程开发中,除了synchronized这个关键字外,我们还能通过Lock接口来实现这种效果.通过Lock接口来实现 这种多线程加锁效果的好处是非常的灵活,我们不在需要对整个函数加锁,而且可以很方便的把他放在我们函数的任何 一个地方,非常的称心,而且从效率上来说,使用Lock接口要比使用synchronized关键字效率高一些,下面我们来使用 一个例子来说明这种方法的使用. package com.bird.concursey.charpet3; public class Job imple

Cannot lock storage /tmp/hadoop-root/dfs/name. The directory is already locked.

[[email protected] bin]# ./hadoop namenode -format 12/05/21 06:13:51 INFO namenode.NameNode: STARTUP_MSG: /************************************************************ STARTUP_MSG: Starting NameNode STARTUP_MSG:   host = nn01/127.0.0.1 STARTUP_MSG:  

synchronized 和 lock 的区别

lock更灵活,可以自由定义多把锁的加锁解锁顺序(synchronized要按照先加的后解顺序) 提供多种加锁方案,lock 阻塞式, trylock 无阻塞式, lockInterruptily 可打断式, 还有trylock的带超时时间版本. 本质上和监视器锁(即synchronized是一样的) 能力越大,责任越大,必须控制好加锁和解锁,否则会导致灾难. 和Condition类的结合.

SQL Server中如何定位Row Lock锁定哪一行数据

在SQL Server中有时候会使用提示(Hint)强制SQL使用行锁(Row Lock),前两天有个同事咨询了一个问题,如何定位Row Lock具体锁定了哪一行.其实这个问题只适合研究一下,实际意义并不大,因为找到.定位被锁定的行的代价开销较大,而意义却不怎么大,而且使用场景也很少.那么下面我们来探讨.研究一下这个问题吧: 在会话窗口(会话ID=65)下执行下面SQL语句,模拟SQL Server使用行锁锁定某一行记录: USE AdventureWorks2012; GO   SELECT