美文网首页
线程同步(通信)

线程同步(通信)

作者: 哓晓的故事 | 来源:发表于2018-05-31 09:01 被阅读0次

线程分类

普通线程:主线程创建的所有子线程都是普通线程
守护线程:JVM停止时,抛弃所有守护线程,不执行finally代码块,也不会回收栈

synchronozied

同步方法、同步代码块必须获取对应的监视器monitor
线程之间的相互唤醒属于内存通信机制,Java中使用notify和wait来实现,并且必须在synchronized语句块内使用

注意: 启动一个线程,应该给线程命名,方便监控和排查问题

condition

由于 wait/notify/notifyAll 必须依赖 synchronized,太重不方便使用
可以使用ReentrantLock的condition,一个锁可以创建多个通信condition

ConditionObject 和 Object 通信方式
wait=await
notify=signal
notifyAll=signalAll

一个 ReentrantLock 可以有多个 ConditionObject
而 synchronized 把 lock 和 condition合并了,一个sync只对应一个condition
并且不要在lock/condition`上使用 wait/notify/notifyAll

wait 与 sleep

Thread.sleep()与Object.wait()二者都可以暂停当前线程释放CPU控制权,主要的区别在于wait()在释放CPU同时,释放了对象锁(监控器monitor)的控制

未取得锁(必须是synchronized,ReentrantLock也不行)就直接执行wait、notfiy、notifyAll会抛异常

等待队列condition - 监视器monitor

关键点是条件谓词,条件谓词涉及状态变量,状态变量由保护,所以在测试条件谓词需要先持有
永远在循环中使用wait/await,并且条件是条件谓语,且条件谓词的状态变量保护

每个Java对象有一个监视器monitor,实现了同步队列等待队列,且二者是相关的, 区别是 sync 的队列是放在 monitorobject header 中.

参考 reetrantLock 原理, 使用 同步队列等待队列 来实现.

监视器.png
lock-monitor.png
每个Object或者Class都拥有一个monitor
monitor保证每次只能有一个线程能进入这个房间进行访问被保护的数据
进入房间即为acquire monitor
退出房间即为release monitor
否则进入entry set/wait set队列等待抢占资源
这个队列不是真正的排序,而是唤醒所有等待的线程竞争资源(因为是非公平的)

notify/notifyAll

notify 只会唤起一个wait线程,如果存在多个谓词,存在丢失通知信号的问题,如果只有一个条件谓词,性能足够好。如果Lock的条件队列condition有多个,可以使用notify,(但是notify并不会立即释放monitor,而是等同步块结束才释放

notifyAll 会唤起所有的wait线程,性能不足够好,但是能兼容多个谓词的情况,synchronized的条件队列condition只有一个,但是谓词却又多个,建议使用notifyAll

notify/notifyAll的时候,没有wait的线程,信号就丢失了

interrupt()

线程没有直接终止方法
线程中断的协作机制,协作更合理,留给线程停下手中的动作,然后再终止
修改线程中断状态 -> 表示当前线程应该停止运行,但是当前线程不会立即停止

Thread.sleep();
Thread.join();
Object.wait();

以上动作在监听线程状态位被置为中断,会立即抛出InterruptedException异常
程序应该对线程中断做出响应Thread.interrupted()方法来判断当前线程状态是否被设置为中断状态但是,interrupted()会清空线程的中断状态,除非想ignored这个中断,否则就需要捕获InterrupedException处理或者使用.interrupt()向上反馈中断

异常的线程终止

  1. 非interruped的异常,导致线程中断,在ThreadPool的处理方式是重建一个线程

阻塞队列 BlockingQueue

生产者/消费者 模式中大量使用
take() 如果队列空,会阻塞直到队列有值
put()如果队列满,会阻塞直到队列有空间
offer()如果队列满,会快速返回失败状态

共享变量

1. 线程封闭

  1. ad-hoc
  2. 栈限制,只在栈内生成对象,不对外逃逸
  3. 使用threadLocal

2. 线程不可变

  1. final

相关文章

  • Java内存模型

    线程之间的通信和同步 线程之间的通信和同步是并发编程领域的关键问题。 线程之间的通信 通信是指线程之间以何种机制来...

  • 2.Java内存模型

    1.java并发编程的线程间通信及线程间如何同步线程间通信分为:共享内存,消息传递。线程间同步:共享内存是代码指定...

  • java内存模型

    1、并发编程中有两个关键问题:线程通信和线程同步a、线程通信:是指线程之间通过何种机制来进行信息的交换b、线程同步...

  • 线程同步(通信)

    线程分类 普通线程:主线程创建的所有子线程都是普通线程守护线程:JVM停止时,抛弃所有守护线程,不执行finall...

  • JAVA进阶(4)—— 内存模型

    基础 并发编程需要处理的两个关键问题:线程通信和线程同步 线程通信 线程通信的两种方式:共享内存和消息传递 共享...

  • Java多线程(四)使用synchronized锁实现线程同步

    本篇本章主要介绍以synchronized关键字的方式实现线程同步,以及线程间的通信。 为什么要用线程同步####...

  • 进程/多线程

    进程与线程 线程 创建定时器 线程同步synchronized 线程通信-wait/notify Lock&Con...

  • 线程同步及通信机制

    线程同步 线程同步是保证多线程安全访问竞争资源的一种手段 线程间通信 线程间往往需要协调,共同完全某项工作,需要线...

  • 线程间通信

    线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。 1)锁机制:包括互斥锁、条...

  • 进程的同步与通信,进程与线程同步的区别,进程与线程通信的区别

    进程同步与互斥的区别? 进程的同步方式有哪些? 进程的通信方式有哪些? 进程同步与通信的区别是什么? 线程的同步/...

网友评论

      本文标题:线程同步(通信)

      本文链接:https://www.haomeiwen.com/subject/ghczrftx.html