线程之间的通信

        有的时候我们需要来控制线程之间的执行顺序,而线程之间的通信就借助于变量之间的关系,比如在变量是什么状态下让什么线程来执行。

        当我们在使用同步锁的时候可以使用object的wait(),notify(),notifyAll()来控制线程是否等待,是否被唤醒。

       这三个方法的使用需要注意,三个方法的调用者必须是监视锁对象本身。synchronized(监视锁对象)这句话中的监视锁对象需要跟wait(),notify(),notifyAll()的调用者一致,否则会出现监视锁异常。

        下面使用一个简单的购票的例子来说明线程之间的通信:

        购票规则是只要是有票,生产票的线程就等待,直到没有票的时候被唤醒。消费票的线程相反,如果没有票就等待,直到有票之后被唤醒。

下面使用synchronized同步锁来演示:

从结果看出来我们实现了线程之间的通讯,只要是有票生产者就会被阻塞住,为什么需要使用synchronized关键字呢?

是因为我们在线程通信时,唤醒的线程是获得了对象同步锁的线程。因此我们需要使用synchronized关键字。

除了使用synchronized关键字我们还可以使用reentrantlock(可重入锁)来保证线程安全,使用condition对象来保证线程通信

方法有await();signal();signalAll().

在使用condition的时候需要先给reentrantlock对象加锁

伪代码如下

ReentrantLock lock = new ReentrantLock();

Condition condition = lock.newCondition();

代码块

try{

//加锁

lock.lock()

//需要进行线程通信的地方

condition.await();

}finally{

//一定需要记住关闭锁,一般写在finally中,因为有可能异常发生,导致锁不能关闭使得其他的线程处于阻塞中

    lock.unlock()

}

除此之外我们还可以使用阻塞队列,阻塞队列其实就是queue的一个实现类,多了一个put和take方法,这两个方法的内部都是加了可重入锁的,如下图(jdk源码):

可以看到如果在操作队列的时候队列内部为空则当前线程会被阻塞住,同理put。其他的方法会加上同步锁但是不会使得线程阻塞 如下图:

        除此之外还有可重入读写锁,在获得读锁的线程上可以再加上写锁,读锁还可以被共享,但是如果之前加上了写锁,就不可以共享锁,且读写锁之间互斥,写写锁之间也是互斥的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值