JAVA并发编程

并发编程详解

注意点:

1、不要调用常量字符串或全局对象的 wait() 方法

通过常量字符串 String 来调用 wait() 或 notify() 方法所导致的问题是,JVM/编译器会在内部自动将内容相同的 String 转变为相同的对象。这意味着,即便你创建了两个不同的 MyWaitNotify 实例,他们内部的 myMonitorObject 变量也会指向相同的 String 对象。这将导致一个非预期的线程中的 notify() 方法会唤醒另睡眠中的线程。
2、volatile 关键字保证了一个变量在不同线程间的可见性。
3、volatile前提: 多个线程在读写 volatile 变量时新计算并写入的变量值不依赖于其历史值,换言之,就是说只要一个线程在写入一个 volatile 变量之前不需要先读取它再计算出新的数值,就不会出现问题。单个写,不受此限制。
4、由于 volatile 变量的读写都要直达主内存,而读写主内存要比读写 CPU 的缓存更加的费时
5、如果一段代码没持有一个对象的锁,就无法调用这个对象的 wait(),notif() 或 notifyAll() 方法。
6、在一些情况下死锁的情况是可以被预防的,三种相关的技术 —— 顺序锁(Lock Ordering)、超时锁(Lock Timeout)和死锁探测(Deadlock Detection)
顺序锁:死锁发生在多个线程都需要相同的(一系列)锁,但是所需要的顺序不同。如果可以确定任意的线程都以相同的顺序使用这些锁,那么死锁就不会发生。这种不同的线程间通以相同的顺序使用锁来预防死锁发生的办法就称为顺序锁。
顺序锁是一个简单但高效的预防死锁的机制。但其前提是要预先知道所有锁的执行顺序,然而这有时是无法办到的。
超时锁:一个线程只会尝试获取一个锁一段时间,随后就放弃。如果时限内这个线程没能成功的获取其本想获得的全部的锁,这个线程就会备份并释放掉已经获得的全部锁资源,再等待一个随机的时长,然后重新从头开始尝试。
然而,即便触发了超时,也不一定意味着发生了死锁,很可能只是一个线程所处理的任务非常费时。另外一点是,即便引入超时的机制,如果足够多的线程竞争相同的锁,依旧会使得死锁的发生概率很高。
死锁探测:每次一个线程实际获得一个锁时,那么就在某个数据结构(映射、图等,你可以自己定义)中做一个获得标记;每当一个线程需要获得一个锁时,也将在这个数据结构中做一个需求标记。如此一来,当一个线程请求一个锁但是无法获得时,这个线程就遍历这个数据结构来探测死锁。
探测到死锁后,一种可能的解决方案是所有的线程释放掉所有的锁,每个等待一个随机的时长然后重新尝试,但问题同上。一个更好的选择是为不同的线程分配优先级,使得只有一个或很少的线程释放掉其持有的锁资源,而其他的线程正常运作。但是如果各个线程间的优先级是确定的话,相同的线程可能总是获得较低的优先级而无法被执行。为了避免这一情况发生,需要在死锁发生时随机分配优先级。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值