JAVA多线程之Lock

synchronized关键字实现的锁不容易控制,java提供了Lock接口来实现锁机制。
两者的主要区别在于:

  • 1)synchronized是java内置关键字,而Lock是接口;
  • 2)synchronized可以自动的释放锁,比如代码执行完成,出现异常等,也可以通过wait()方法手动释放锁;但是Lock需要用unlock方法手动释放锁。
  • 3)synchronized锁可重入,不可判断,非公平,Lock锁可重入,可公平可不公平,可判断;
  • 4)用synchronized的两个线程,如果线程A获得锁并阻塞,线程B会一直等待下去,而Lock锁不一定会持续等待

(1) Lock实现锁的同步
使用Lock实现同步示例:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDem
{
    static Lock lock = new ReentrantLock();

    public static void main(String[] args)
    {
        new Thread(new Runnable(){

            @Override
            public void run()
            {
                lockMethod(lock);

            }
        },"thread1").start();

        new Thread(new Runnable(){

            @Override
            public void run()
            {
                lockMethod(lock);

            }
        },"thread2").start();

    }

    public static void lockMethod(Lock lock){
        lock.lock();
        System.out.println("线程" + Thread.currentThread().getName() + "获取到锁");
        for(int i = 0; i < 5; i++){
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            System.out.println("thread : " + Thread.currentThread().getName() + " " + i);
        }
        lock.unlock();

    }

}

(2)lock实现锁的等待/通知
使用lock condition中的await方法和signal方法实现线程之间的等待/通知,同一个condition之间可以实现互相等待通知,不同的condition可以实现隔离。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo2
{
    private Lock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();

    public static void main(String[] args)
    {
        LockDemo2 demo2 = new LockDemo2();
        new Thread(new Runnable(){

            @Override
            public void run()
            {
                demo2.await(demo2.condition1);

            }
        },"thread1").start();
        new Thread(new Runnable(){

            @Override
            public void run()
            {
                demo2.await(demo2.condition2);

            }
        },"thread2").start();

        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        new Thread(new Runnable(){

            @Override
            public void run()
            {
                demo2.signal(demo2.condition1);

            }
        },"thread3").start();

    }

    public void await(Condition condition){
        try
        {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "开始await");
            condition.await();
            System.out.println(Thread.currentThread().getName() + "结束await");
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }finally
        {
            lock.unlock();
        }
    }

    public void signal(Condition condition){
        try
        {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "开始signal");
            condition.signal();
            System.out.println(Thread.currentThread().getName() + "结束signal");
        }catch (Exception e){
            e.printStackTrace();
        }finally
        {
            lock.unlock();
        }
    }
}

运行结果:thread2 await之后,由于没有现成被通知到,所以不能结束await.

thread1开始await
thread2开始await
thread3开始signal
thread3结束signal
thread1结束await

(3)lock实现读写锁
读写锁 ReentrantReadWriteLock实现读写锁ReadWriteLock,加锁lock.readLock.lock()/lock.writeLock.lock,
解锁lock.readLock.unlock()/ lock.writeLock.lock()。
读写锁能够实现,读读共享,读写/写读互斥,写写互斥。

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class LockDemo3
{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String[] args)
    {
        LockDemo3 demo3 = new LockDemo3();
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                demo3.readLock();
            }
        },"thread1").start();

        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                demo3.readLock();
            }
        },"thread2").start();

        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                demo3.writeLock();
            }
        },"thread3").start();

        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                demo3.writeLock();
            }
        },"thread4").start();
    }

    //读锁
    public void readLock(){
        try
        {
            lock.readLock().lock();
            System.out.println(Thread.currentThread().getName() + "获取到读锁" + System.currentTimeMillis());
            Thread.sleep(3000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }finally
        {
            lock.readLock().unlock();
        }
    }

    //写锁
    public void writeLock(){
        try
        {
            lock.writeLock().lock();
            System.out.println(Thread.currentThread().getName() + "获取到写锁"  + System.currentTimeMillis());
            Thread.sleep(3000);
        }catch (Exception e){
            e.printStackTrace();
        }finally
        {
            lock.writeLock().unlock();
        }
    }
}

运行结果:

thread1获取到读锁1551929162893
thread2获取到读锁1551929162904
thread3获取到写锁1551929166201
thread4获取到写锁1551929169498
Process finished with exit code 0

参考博文: https://blog.csdn.net/xlgen157387/article/details/78197583

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值