首先談?wù)?lock和Synchronized的區(qū)別:
synchronized是Java的一個關(guān)鍵字,也就是Java語言內(nèi)置的特性,如果一個代碼塊被synchronized修飾了,當(dāng)一個線程獲取了對應(yīng)的鎖,執(zhí)行代碼塊時,其他線程便只能一直等待,等待獲取鎖的線程釋放鎖,而獲取鎖的線程釋放鎖會有三種情況:
1).獲取鎖的線程執(zhí)行完該代碼塊,然后線程釋放對鎖的占有;
2).線程執(zhí)行發(fā)生異常,此時JVM會讓線程自動釋放鎖;
3).調(diào)用wait方法,在等待的時候立即釋放鎖,方便其他的線程使用鎖.
Lock不是Java語言內(nèi)置的
1).synchronized是在JVM層面上實現(xiàn)的,如果代碼執(zhí)行出現(xiàn)異常,JVM會自動釋放鎖,但是Lock不行,要保證鎖一定會被釋放,就必須將unLock放到finally{}中(手動釋放);
2).在資源競爭不是很激烈的情況下,Synchronized的性能要優(yōu)于ReetarntLock,但是在很激烈的情況下,synchronized的性能會下降幾十倍;
lock鎖分為兩種鎖,ReentrantLock 和 ReadWriteLock。
ReentrantLock同步鎖聲明:
Lock lock = new ReentrantLock();
例:線程打印 1 2 3 4 舷丹,線程一打印13(奇數(shù))兔跌,線程二打印24(偶數(shù))
synchronized方式實現(xiàn)方式:
public class Demo5 {
public static void main(String[] args) {
Object object = new Object();
int[] count = {1};
Thread thread1 = new Thread(() -> {
for(int i = 0;i<2;i++){
synchronized(object){
while (count[0]%2 ==0){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("thread1:"+count[0]);
count[0]++;
object.notify();//線程喚醒纸颜,隨機(jī)喚醒席爽,哪個先搶到了cpu資源誰喚醒
}
}
});
Thread thread2 = new Thread(() -> {
for(int i = 0;i<2;i++){
synchronized(object){
while (count[0]%2 !=0){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("thread2:"+count[0]);
count[0]++;
object.notify();
}
}
});
thread1.start();
thread2.start();
}
}
運(yùn)行結(jié)果:
Connected to the target VM, address: '127.0.0.1:57332', transport: 'socket'
thread1:1
thread2:2
thread1:3
thread2:4
Disconnected from the target VM, address: '127.0.0.1:57332', transport: 'socket'
Lock實現(xiàn)方式:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo1 {
public static void main(String[] args) {
int[] count = {1};
Lock lock = new ReentrantLock();
Thread thread1 = new Thread(() -> {
for(int i = 0;i<2;){
try {
lock.lock();
while (count[0]%2 != 0){
System.out.println("thread1:"+count[0]);
count[0]++;
i++;
}
}finally {
lock.unlock();
}
}
});
Thread thread2 = new Thread(() -> {
for(int i = 0;i<2;){
try {
lock.lock();
while (count[0]%2 == 0){
System.out.println("thread2:"+count[0]);
count[0]++;
i++;
}
}finally {
lock.unlock();
}
}
});
thread1.start();
thread2.start();
}
}
上面已經(jīng)說過lock不能自動釋放線程鎖稿壁,所以佑女。
一定一定要記得手動釋放線程卵惦。
運(yùn)行結(jié)果:
thread1:1
thread2:2
thread1:3
thread2:4