一、为什么1.5后会引入Concurrent包
其实应该这样说 Synchronized 有什么局限性:
不能一处加锁,另一处释放;没有超时机制;没有公平机制;没有读写功能;。。。
- 严格的块结构
- 活跃性问题
- 改变锁的语义:重入性、读写保护、公平性
- 访问控制
二、Java原生提供的锁工具有哪些
- Synchronized
- Object.wait()
- Object.notify()
- Object.notifyAll()
PS:JavaSynchronized是基于每线程而不是没调用
三、处理(不能一处加锁,另一处释放)的问题
public class Mutex {
protected volatile boolean inuse = false;
public void acquire() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
synchronized (this) {
try {
while (inuse)
wait();
inuse = true;
} catch (InterruptedException ex) {
notify();
throw ex;
}
}
}
public synchronized void release() {
inuse = false;
notify();
}
}
四、实践
上述的锁支持在一处加锁,在另一处释放。是骡子是马,拉出来溜溜!
一个常见的并发编程题,两个线程交替打印奇数和偶数:
import com.google.common.base.Joiner; import java.util.concurrent.TimeUnit; public class TurnOutPut { private static int index = 1; private boolean isOdd = true; private boolean isEven = true; public void oddOutput(Mutex mutex) { while (true) { try { mutex.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } if (!isOdd) { mutex.release(); continue; } try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Joiner.on("").join("【odd】", "id: ", Thread.currentThread().getId(), ", val: ", index++)); isOdd = false; isEven = true; mutex.release(); } } public void evenOutput(Mutex mutex) { while (true) { try { mutex.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } if (!isEven) { mutex.release(); continue; } try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Joiner.on("").join("【even】", "id: ", Thread.currentThread().getId(), ", val: ", index++)); isEven = false; isOdd = true; mutex.release(); } } public static void main(String[] args) throws InterruptedException { final TurnOutPut turnOutPut = new TurnOutPut(); final Mutex mutex = new Mutex(); new Thread(new Runnable() { public void run() { turnOutPut.oddOutput(mutex); } }).start(); new Thread(new Runnable() { public void run() { turnOutPut.evenOutput(mutex); } }).start(); Thread.currentThread().join(); } }
五、分析&问题
Mutex类volatile关键字不需要可以吗?
synchronized、wait、notify之间的关系是怎样的?
synchronized到底在同步什么?
wait在等待什么?
notify在通知什么?
Mutex是不完备的,如果恶意的线程直接调用release怎么办?