java多线程-ReentranLock
一、ReentranLock
ReentranLock公平锁和非公平锁的创建
//创建公平锁
Lock fairLock = new ReentranLock(true);
//创建非公平锁
Lock fairLock = new ReentranLock();
Lock fairLock = new ReentranLock(false);
ReentranLock公平锁和非公平锁之间的区别
ReentranLock使用方式
Class X{
//定义一个锁
private final Lock lock = new ReentranLock();
public void method(){
try{
lock.lock();//获得锁
/*此处是临界资源*/
}finally{
lock.unlock();//释放锁
}
}
}
二、 多个线程访问同一个对象的同一个ReentranLock锁定的方法中的
package java_lang_Object;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by luckyboy on 2018/7/7.
*/
public class ReentrantLockTest {
public static void main(String[] args){
ThreadDomain3 threadDomain3 = new ThreadDomain3();
MyThread7_9 thread1 = new MyThread7_9(threadDomain3);
MyThread7_9 thread2 = new MyThread7_9(threadDomain3);
MyThread7_9 thread3 = new MyThread7_9(threadDomain3);
thread1.start();
thread2.start();
thread3.start();
}
}
class ThreadDomain3{
private Lock lock = new ReentrantLock();
public void methodA(){
try{
lock.lock();
System.out.println(Thread.currentThread().getName()+"进入methodA");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+"sleep 2s 后退出methodA");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
class MyThread7_9 extends Thread{
private ThreadDomain3 threadDomain3;
public MyThread7_9(ThreadDomain3 threadDomain3){
this.threadDomain3 = threadDomain3;
}
@Override
public void run(){
this.threadDomain3.methodA();
}
}
输出结果
Thread-0进入methodA
Thread-0 sleep 2s 后退出methodA
Thread-1进入methodA
Thread-1 sleep 2s 后退出methodA
Thread-2进入methodA
Thread-2 sleep 2s 后退出methodA
2、我们在ThreadDomain的lock.lock()方法上添加一条语句
class ThreadDomain3{
private Lock lock = new ReentrantLock();
public void method1(){
try{
//在lock.lock()方法上添加这条语句
System.out.println(Thread.currentThread().getName()+"将要进入methodA");
lock.lock();
System.out.println(Thread.currentThread().getName()+"进入methodA");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+"sleep 2s 后退出methodA");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
输出结果
Thread-1将要进入methodA
Thread-0将要进入methodA
Thread-2将要进入methodA
Thread-1进入methodA
Thread-1 sleep 2s 后退出methodA
Thread-0进入methodA
Thread-0 sleep 2s 后退出methodA
Thread-2进入methodA
Thread-2 sleep 2s 后退出methodA
结论:
- 对于多个线程访问同一个对象的同一个方法,对于lock.lock()调用之前的代码都是可入的。对于lock.lock()之后的代码,各个线程是同步的。
ReentranLock
1、当我们两个线程使用相同的对象
package java_lang_Object;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by luckyboy on 2018/7/7.
*/
public class ReentrantLockTest {
public static void main(String[] args){
ThreadDomain3 threadDomain3 = new ThreadDomain3();
MyThread7_9 thread1 = new MyThread7_9(threadDomain3);
MyThread7_10 thread2 = new MyThread7_10(threadDomain3);
//MyThread7_9 thread3 = new MyThread7_9(threadDomain3);
thread1.start();
thread2.start();
//thread3.start();
}
}
class ThreadDomain3{
private Lock lock = new ReentrantLock();
public void methodA(){
try{
lock.lock();
System.out.println(Thread.currentThread().getName()+"进入methodA");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+" sleep 2s 后退出methodA");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void methodB(){
try{
lock.lock();
System.out.println(Thread.currentThread().getName()+"进入methodB");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+" sleep 2s 后退出methodB");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
class MyThread7_9 extends Thread{
private ThreadDomain3 threadDomain3;
public MyThread7_9(ThreadDomain3 threadDomain3){
this.threadDomain3 = threadDomain3;
}
@Override
public void run(){
this.threadDomain3.methodA();
}
}
class MyThread7_10 extends Thread{
private ThreadDomain3 threadDomain3;
public MyThread7_10(ThreadDomain3 threadDomain3){
this.threadDomain3 = threadDomain3;
}
@Override
public void run(){
this.threadDomain3.methodB();
}
}
输出结果
Thread-0进入methodA
Thread-0 sleep 2s 后退出methodA
Thread-1进入methodB
Thread-1 sleep 2s 后退出methodB
2、当我们使用的是不同的对象时,会发生什么
public class ReentrantLockTest {
public static void main(String[] args){
ThreadDomain3 threadDomain3 = new ThreadDomain3();
MyThread7_9 thread1 = new MyThread7_9(threadDomain3);
ThreadDomain3 threadDomain4 = new ThreadDomain3();
MyThread7_10 thread2 = new MyThread7_10(threadDomain4);
thread1.start();
thread2.start();
}
}
结论
- ReentranLock调用lock方法获得的是对象锁,如果两个线程使用同一个对象,那么调用lock(),会竞争这个对象锁。线程执行时同步的
- 当两个线程使用不同的对象时,因为lock()使用的是不同的对象锁,这个时候两个线程是异步执行的
一个使用synchronized方法,而另一个方法使用ReentranLock
package java_lang_Object;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by luckyboy on 2018/7/7.
*/
public class ReentrantLockTest {
public static void main(String[] args){
ThreadDomain3 threadDomain3 = new ThreadDomain3();
MyThread7_9 thread1 = new MyThread7_9(threadDomain3);
ThreadDomain3 threadDomain4 = new ThreadDomain3();
MyThread7_11 thread2 = new MyThread7_11(threadDomain4);
//MyThread7_9 thread3 = new MyThread7_9(threadDomain3);
thread1.start();
thread2.start();
//thread3.start();
}
}
class ThreadDomain3{
private Lock lock = new ReentrantLock();
public void methodA(){
try{
//System.out.println(Thread.currentThread().getName()+"将要进入methodA");
lock.lock();
System.out.println(Thread.currentThread().getName()+"进入methodA");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+" sleep 2s 后退出methodA");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void methodC(){
synchronized (this){
System.out.println(Thread.currentThread().getName()+"进入methodB");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" sleep 2s 后退出methodB");
}
}
}
class MyThread7_9 extends Thread{
private ThreadDomain3 threadDomain3;
public MyThread7_9(ThreadDomain3 threadDomain3){
this.threadDomain3 = threadDomain3;
}
@Override
public void run(){
this.threadDomain3.methodA();
}
}
class MyThread7_11 extends Thread{
private ThreadDomain3 threadDomain3;
public MyThread7_11(ThreadDomain3 threadDomain3){
this.threadDomain3 = threadDomain3;
}
@Override
public void run(){
this.threadDomain3.methodC();
}
}
输出结果
Thread-0进入methodA
Thread-1进入methodB
Thread-0 sleep 2s 后退出methodA
Thread-1 sleep 2s 后退出methodB
结论
synchronized和ReentranLock都会持有对象锁,但是synchronized和ReentranLock持有的对象锁又有所不同(明天解决)
ReentranLock结合Condition实现线程之间通信
ReeTranLock+Condition.await()+Condition.signal组合与synchronized+Object.wait()+Object.notify()/notifyAll()组合的功能是一样的
Lock lock = new ReentranLock();//创建一个ReentranLock对象
Condition condition = lock.newCondition();//获取Condition对象
ReentranLock和synchronized之间的区别和联系
参考文章
详情请去下面大佬去学习,写得非常棒,本人只是知识搬运工
http://www.cnblogs.com/xrq730/p/4855155.html
https://blog.csdn.net/yanyan19880509/article/details/52345422/
http://www.cnblogs.com/-new/p/7256297.html