java多线程-ReentranLock

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

猜你喜欢

转载自blog.csdn.net/makeliwei1/article/details/80955055