Lock是顶层接口,它的实现逻辑并未用到synchronized,而是利用了volatile的可见性。ReentrantLock对了Lock接口的实现主要依赖了Sync,而Sync继承了

 AbstractQueuedSynchronizer(AQS)

 ReentrantLock:

public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
/** Synchronizer providing all implementation mechanics */
private final Sync sync; /**
* Base of synchronization control for this lock. Subclassed
* into fair and nonfair versions below. Uses AQS state to
* represent the number of holds on the lock.
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L; /**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock(); /**
* Performs non-fair tryLock. tryAcquire is
* implemented in subclasses, but both need nonfair
* try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
} protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
} protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
} final ConditionObject newCondition() {
return new ConditionObject();
} // Methods relayed from outer class final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
} final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
} final boolean isLocked() {
return getState() != 0;
} /**
* Reconstitutes this lock instance from a stream.
* @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
}

在AQS中,定义了一个volatile int state 变量作为共享资源。

 /**
* The synchronization state.
*/
private volatile int state;

如果线程获取此共享资源失败,则进入同步FIFO队列中等待;如果成功获取资源就执行临界区代码。执行完释放资源时,会通知同步队列中的等待线程来获取资源后出对并执行。

看其lock方法:

首先默认构造是非公平锁,所谓的公平锁就是先等待的线程先获得锁

   public ReentrantLock() {
sync = new NonfairSync();
}

NonfairSync:

/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L; /**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1)) //compareAndSetState(int expect, int update)
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
} protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}

ReentrantLock:

    public void lock() {
sync.lock();
}

所以,默认执行的是NonfairSync中的lock()实现,利用Unsafe类的CAS,期望state值为0时将其值设为1,返回是否成功

    protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

因此ReentrantLock的lock()方法只有在state为0时才能获得锁,并将state设为1。这样其他线程就无法获取锁,只能等待。

由于ReentrantLock是可重入锁,即在获得锁的情况下,可以再次获得锁。并且线程可以进入任何一个它已经拥有的锁所同步着的代码块。若在没有释放锁的情况下,

再次获得锁,则state加1,在释放资源时,state减1,因此Lock获取多少次锁就要释放多少次锁,直到state为0。

Conditon中的await()对应Object的wait(),Condition中的signal()对应Object的notify(),Condition中的signalAll()对应Object的notifyAll()

两个线程交替执行例子(同理生产者消费者也是这样交替执行)

package com.yang.spbo.other.lock;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; /**
* A,B两个线程交替执行
* 〈功能详细描述〉
*
* @author 17090889
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class ConditionService {
private ReentrantLock lock = new ReentrantLock();
/**
* 两个线程所以创建两个condition
*/
private Condition A = lock.newCondition();
private Condition B = lock.newCondition(); private int number = 1; private boolean flag = false; private void executeA() {
while (number < 100) {
try {
lock.lock();
if (!flag) {
System.out.println("A等待");
A.await();
}
System.out.println("A " + number);
number++;
flag = false;
System.out.println("B唤醒");
B.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} } private void executeB() {
while (number < 100) {
try {
lock.lock();
if (flag) {
System.out.println("B等待");
B.await();
}
System.out.println("B " + number);
number++;
flag = true;
System.out.println("A唤醒");
A.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} } public static void main(String[] args) {
final ConditionService cs = new ConditionService();
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 1, TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>(1000), new MyThreadFactory("conditionService")); executor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
cs.executeA();
}
});
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
cs.executeB();
}
});
} static class MyThreadFactory implements ThreadFactory {
/**
* 线程名字前缀
*/
private String namePrefix; private AtomicInteger id = new AtomicInteger(1); public MyThreadFactory(String namePrefix) {
this.namePrefix = namePrefix;
} @Override
public Thread newThread(Runnable r) {
String threadName = namePrefix + "-worker-" + id.getAndIncrement();
Thread thread;
thread = new Thread(r, threadName);
return thread;
}
}
}

运行结果:

conditionService-worker-1
A等待
conditionService-worker-2
B 1
A唤醒
B等待
A 2
B唤醒
A等待
B 3
A唤醒
B等待
A 4
B唤醒
A等待
B 5
A唤醒
B等待
A 6

ReentrantLock实现死锁:

/**
* ReentrantLock实现死锁
* 〈功能详细描述〉
*
* @author 17090889
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class DeadLockTest {
private static ReentrantLock lock1 = new ReentrantLock();
private static ReentrantLock lock2 = new ReentrantLock(); public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
lock1.lock();
try {
Thread.sleep(1000);
lock2.lock();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock1.unlock();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
lock2.lock();
try {
Thread.sleep(1000);
lock1.lock();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock2.unlock();
} }
}).start();
}
}
分析过程:
1.
c:\Program Files\Java\jdk1.7.0_79\bin>jps
7996 Main
3960 Jps
8396 Launcher
5568 Launcher
1204
8212 Bootstrap
396 ProfilerServer
8036 DeadLockTest
 
2.c:\Program Files\Java\jdk1.7.0_79\bin>jstack 8036
Found one Java-level deadlock:
=============================
"Thread-1":
  waiting for ownable synchronizer 0x00000007d5e6f5c0, (a java.util.concurrent.l
ocks.ReentrantLock$NonfairSync),
  which is held by "Thread-0"
"Thread-0":
  waiting for ownable synchronizer 0x00000007d5e6f5f0, (a java.util.concurrent.l
ocks.ReentrantLock$NonfairSync),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000007d5e6f5c0> (a java.util.concurrent.lock
s.ReentrantLock$NonfairSync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInt
errupt(AbstractQueuedSynchronizer.java:834)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(A
bstractQueuedSynchronizer.java:867)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Abstrac
tQueuedSynchronizer.java:1197)
        at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLo
ck.java:214)
        at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)

at deadLock.DeadLockTest$2.run(DeadLockTest.java:38)
        at java.lang.Thread.run(Thread.java:745)
"Thread-0":
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000007d5e6f5f0> (a java.util.concurrent.lock
s.ReentrantLock$NonfairSync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInt
errupt(AbstractQueuedSynchronizer.java:834)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(A
bstractQueuedSynchronizer.java:867)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Abstrac
tQueuedSynchronizer.java:1197)

        at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLo
ck.java:214)
        at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
 
        at deadLock.DeadLockTest$1.run(DeadLockTest.java:24)
        at java.lang.Thread.run(Thread.java:745)
 
Found 1 deadlock.

 synchronized实现死锁:

/**
* synchronized实现死锁
* 〈功能详细描述〉
*
* @author 17090889
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class DeadLockTest2 {
private static Object obj1 = new Object();
private static Object obj2 = new Object(); public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj1) {
System.out.println("thead1 get lock1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2) {
System.out.println("thead1 get lock2");
}
System.out.println("thread1 end");
}
}
}, "thead1").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj2) {
System.out.println("thead2 get lock2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj1) {
System.out.println("thead2 get lock1");
}
System.out.println("thread2 end");
}
}
}, "thead2").start();
}
}
Found one Java-level deadlock:
=============================
"thead2":
  waiting to lock monitor 0x000000000b15a7c8 (object 0x00000007d5e6f290, a java.
lang.Object),
  which is held by "thead1"
"thead1":
  waiting to lock monitor 0x000000000b1593d8 (object 0x00000007d5e6f2a0, a java.
lang.Object),
  which is held by "thead2"

Java stack information for the threads listed above:
===================================================
"thead2":
        at deadLock.DeadLockTest2$2.run(DeadLockTest2.java:44)
        - waiting to lock <0x00000007d5e6f290> (a java.lang.Object)
        - locked <0x00000007d5e6f2a0> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:745)
"thead1":
        at deadLock.DeadLockTest2$1.run(DeadLockTest2.java:27)
        - waiting to lock <0x00000007d5e6f2a0> (a java.lang.Object)
        - locked <0x00000007d5e6f290> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

Lock之ReentrantLock及实现生产者消费者和死锁的更多相关文章

  1. Java实现生产者消费者问题与读者写者问题

    摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从 ...

  2. 生产者消费者模式--阻塞队列--LOCK,Condition--线程池

    1.阻塞队列:http://www.cnblogs.com/dolphin0520/p/3932906.html 2.Condition 生产者消费者实现 :http://www.cnblogs.co ...

  3. 【多线程】--生产者消费者模式--Lock版本

    在JDK1.5发布后,提供了Synchronized的更优解决方案:Lock 和 Condition 我们使用这些新知识,来改进例子:[多线程]--生产者消费者模式--Synchronized版本 改 ...

  4. 使用Lock锁生产者消费者模式

    package com.java.concurrent; import java.util.concurrent.locks.Condition; import java.util.concurren ...

  5. java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比

    package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...

  6. Java 学习笔记 使用并发包ReentrantLock简化生产者消费者模式代码

    说明 ReentrantLock是java官方的一个线程锁类,ReentarntLock实现了Lock的接口 我们只需要使用这个,就可以不用使用synchronized同步关键字以及对应的notify ...

  7. 生产者消费者两种实现:wait/notifyAll和Lock/Condition

    1.wait/notifyAll /** * 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法, * 能够支持2个生产者线程以及10个消费者线程的阻塞调用 * * 使用 ...

  8. 生产者消费者 java.util.concurrent.lock包

    package com.mozq.thread.producer2; import java.util.concurrent.locks.Condition; import java.util.con ...

  9. Java 多线程之生产者消费者(多个生成者多个消费者)synchronized 和lock多线程通讯和同步实现

    public class ProducterConsumerSample { public static void main(String[] args) { Resourse res = new R ...

随机推荐

  1. qinwoyige

    <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...

  2. 台哥原创:java 数独源码

    2010年,当时正在做手机游戏的客户端开发工作. 每天加班之余,用了两三个晚上,开发了这个数独. 主要是生成数独数组的算法,有点难度.. ​ 如下图:点选数字栏里的数字后,界面上所有该数字会高亮显示. ...

  3. php面试专题---mysql数据库分库分表

    php面试专题---mysql数据库分库分表 一.总结 一句话总结: 通过数据切分技术将一个大的MySQLServer切分成多个小的MySQLServer,既攻克了写入性能瓶颈问题,同一时候也再一次提 ...

  4. Java多线程,实现卖电影票的业务

    本篇重点:多线程共享资源时发生的互斥问题 一般的我们售卖电影票或者火车票时会有多个窗口同时买票, 我们来看测试代码:主方法new一个Ticket(一个堆),之后三个线程来启动(三个窗口买票) clas ...

  5. 第 4 章 前端基础之jquery

    一.jQuery是什么? 1. jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多 javascript高手加入其team. 2. jQuery是继prototype之后又一 ...

  6. JNI-java native interface(java本地接口)

    什么是JNI java native interface(java本地接口) ABI: application binary interface (应用程序二进制接口) 为什么要使用JNI * 复用很 ...

  7. poj1258Agri-Net(最小生成树)

    题目链接:http://poj.org/problem?id=1258 Description Farmer John has been elected mayor of his town! One ...

  8. Yaconf – 一个高性能的配置管理扩展

    鸟哥出品:http://www.laruence.com/2015/06/12/3051.html 首先说说, 这个是干啥的. 我见过很多的项目中, 用PHP文件做配置的, 一个config目录下可能 ...

  9. Linux安装redis服务器和部署

    Linux安装redis和部署 第一步:下载安装包 wget http://download.redis.io/releases/redis-5.0.5.tar.gz 访问https://redis. ...

  10. Vue CLI UI:Vue开发者必不可少的工具

    突然发现一个Vue cli 比较好用的工具,一个可视化图形界面方便你去创建.更新和管理Vue项目.这里分享2个作者写得比较好的文章 https://codeseeding.com/portal.php ...