1.同步代碼塊
synchronized(同步鎖){
需要同步操作的代碼
}
對(duì)象的同步鎖只是一個(gè)概念,可以想象為在對(duì)象上標(biāo)記了一個(gè)鎖.
1. 鎖對(duì)象 可以是任意類型赋荆。
2. 多個(gè)線程對(duì)象 要使用同一把鎖
注意:在任何時(shí)候,最多允許一個(gè)線程擁有同步鎖,誰拿到鎖就進(jìn)入代碼塊,其他的線程只能在外等著
(BLOCKED)。
public class Ticket implements Runnable{
private int ticket = 100;
Object lock = new Object();
/*
* 執(zhí)行賣票操作
*/
@Override
public void run() {
//每個(gè)窗口賣票的操作
//窗口 永遠(yuǎn)開啟
while(true){
synchronized (lock) {
if(ticket>0){//有票 可以賣
//出票操作
//使用sleep模擬一下出票時(shí)間
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto‐generated catch block
e.printStackTrace();
}
//獲取當(dāng)前線程對(duì)象的名字
String name = Thread.currentThread().getName();
System.out.println(name+"正在賣:"+ticket‐‐);
}
}
}
}
}
image.png
2.同步方法
同步方法:使用synchronized修飾的方法,就叫做同步方法,保證A線程執(zhí)行該方法的時(shí)候,其他線程只能在方法外
等著。
同步方法的同步鎖對(duì)象是誰?
對(duì)于非static方法,同步鎖就是this。
對(duì)于static方法,我們使用當(dāng)前方法所在類的字節(jié)碼對(duì)象(類名.class)精绎。
public synchronized void method(){
可能會(huì)產(chǎn)生線程安全問題的代碼
}
public class Ticket implements Runnable{
private int ticket = 100;
/*
* 執(zhí)行賣票操作
*/
@Override
public void run() {
//每個(gè)窗口賣票的操作
//窗口 永遠(yuǎn)開啟
while(true){
sellTicket();
}
}
/*
* 鎖對(duì)象 是 誰調(diào)用這個(gè)方法 就是誰
* 隱含 鎖對(duì)象 就是 this
*
*/
public synchronized void sellTicket(){
if(ticket>0){//有票 可以賣
//出票操作
//使用sleep模擬一下出票時(shí)間
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto‐generated catch block
e.printStackTrace();
}
//獲取當(dāng)前線程對(duì)象的名字
String name = Thread.currentThread().getName();
System.out.println(name+"正在賣:"+ticket‐‐);
}
}
}
3.lock與unlock
public void lock() :加同步鎖薪前。
public void unlock() :釋放同步鎖。
public class Ticket implements Runnable{
private int ticket = 100;
Lock lock = new ReentrantLock();//實(shí)現(xiàn)接口后猿涨,才能調(diào)用接口中的方法
/*
* 執(zhí)行賣票操作
*/
@Override
public void run() {
//每個(gè)窗口賣票的操作
//窗口 永遠(yuǎn)開啟
while(true){
lock.lock();
if(ticket>0){//有票 可以賣
//出票操作
//使用sleep模擬一下出票時(shí)間
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto‐generated catch block
e.printStackTrace();
}
//獲取當(dāng)前線程對(duì)象的名字
String name = Thread.currentThread().getName();
System.out.println(name+"正在賣:"+ticket‐‐);
}
lock.unlock();
}
}
}