刚学编程的时候,不懂得同步的概念,只认为程序按照自己写的顺序执行,
直到学到多线程,但当时理解同步问题,也只是面对临界资源需要加锁去控制,
解决一些,如生产消费的问题。但当时一直没考虑过,多线程的情况下,程序可
能会执行失败的,比如一个Integer变量,多线程去累加,所以同步很重要。
涉及例子一共两个:
https://github.com/xuezhankui/Test/blob/master/src/com/xzk/test/TestSynchronized.java
https://github.com/xuezhankui/Test/blob/master/src/com/xzk/test/TestWaitNotifyMain.java
基本原则:
但实例多线程,锁有效。多class实例,同步无效,因为每个实例分别有锁。
1.sychronized
基本用法是 synchronized(obj){ 代码块 }
或者方法前加synchronized
1) 代码块很好理解,在一个线程执行完之前,下一个线程会等在代码块外,其实是等待拿obj这个锁。
2) 方法前缀,是以该class的实例作为锁,并不是该方法加锁
经测试:
1》.多个方法有synchronized前缀,一个线程调用时,即使另一个线程调用B方法,也许要等待拿到锁才可以。
2》.多个方法中,没有synchronized前缀的方法不会被阻塞
2.Lock
lock只是接口,实现的类有几个,我例子用的ReentrantLock,没有使用公平锁。
基本用法: private ReentrantLock lock = new ReentrantLock();
使用 上, 锁的时候 lock.lock(); 不过要记得释放, lock.unlock(); 简单的方式是try里面lock,finally里面去做unlock。
补充,有个Condition,可以搜一下,可作为条件去,支持wait和notify,只是方法名字不一样。
3. 其他lock
其他锁没怎么看,有个读写锁,基本原则是读锁和写锁分开,写的时候阻塞读,读的时候锁是共享的。有空的时候写写例子再补充
4.wait notify
wait是让当前线程进入等待队列, notify是唤醒一个线程,notifyAll是唤醒所有等待的,然后再竞争锁。如果关注顺序需要用队列。
一般情况下,写法:
synchronized(obj){
while(true){
if(需要等待资源)
obj.wait();
执行完成
obj.notifyAll();
}
}
特别注意:以上只是写法,并不是逻辑,写的时候要注意防止死锁,上面只是生产消费模式中其中一方大概写法。