wordpress問(wèn)答社區(qū)模板合肥seo整站優(yōu)化網(wǎng)站
文章目錄
- 1.存在的問(wèn)題
- 2.使用同步解決問(wèn)題
- 1) synchronized
- 2) volatile
- 3) 鎖
- 總結(jié)
用多線程過(guò)程中,有可能出現(xiàn) 多個(gè)線程同時(shí)處理(獲取或修改等)同一個(gè)數(shù)據(jù),這個(gè)時(shí)候就 會(huì)發(fā)生數(shù)據(jù)不同步的問(wèn)題, 因此出現(xiàn)了同步和鎖來(lái)保證多個(gè)線程可以安全的處理同一個(gè)數(shù)據(jù)。
1.存在的問(wèn)題
例如:火車(chē)售票窗口售票,假如我們有 2 個(gè)窗口(相當(dāng)于開(kāi)啟了 2 個(gè)線程),同時(shí)賣(mài) 10 張票
兩個(gè)窗口的操作流程都如下:
1)購(gòu)票者到窗口
2)窗口訪問(wèn)票匣子獲取余票數(shù)量
3)票匣子返回余票數(shù)量
4)售票窗口判斷,若存在票(大于 0 )則賣(mài)給他
那么,假如票匣子就剩下 1 張票啦!但是不巧的是兩個(gè)窗口同時(shí)查看余票數(shù)量,都發(fā)現(xiàn)還有 1 張票,**又都賣(mài)給了購(gòu)票者……**這就是多線程存在的數(shù)據(jù)不同步問(wèn)題_
示例代碼:
public class Demo {public static void main(String[] args) throws InterruptedException {ThreadDemo threadDemo = new ThreadDemo();new Thread(threadDemo,"售票窗口1").start();new Thread(threadDemo,"售票窗口2").start();}
}class ThreadDemo implements Runnable {private int ticketCount = 10;@Overridepublic void run() {String tName = Thread.currentThread().getName();while (true) {if (ticketCount <= 0) {return;}try {Thread.sleep(200);System.out.println(tName + "成功賣(mài)了一張票!余票:" + (ticketCount-- - 1));} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
輸出結(jié)果:
售票窗口1成功賣(mài)了一張票!余票:9
售票窗口2成功賣(mài)了一張票!余票:8
售票窗口1成功賣(mài)了一張票!余票:7
售票窗口2成功賣(mài)了一張票!余票:6
售票窗口2成功賣(mài)了一張票!余票:5
售票窗口1成功賣(mài)了一張票!余票:4
售票窗口2成功賣(mài)了一張票!余票:3
售票窗口1成功賣(mài)了一張票!余票:2
售票窗口1成功賣(mài)了一張票!余票:1
售票窗口2成功賣(mài)了一張票!余票:0
售票窗口1成功賣(mài)了一張票!余票:-1
2.使用同步解決問(wèn)題
同步(Synchronization) 是一種協(xié)調(diào)多個(gè)線程執(zhí)行的機(jī)制,它能夠確保在同一時(shí)刻只有一個(gè)線程訪問(wèn)共享資源。主要通過(guò)關(guān)鍵字 synchronized
和 volatile
以及 鎖對(duì)象
等手段來(lái)實(shí)現(xiàn)同步。
1) synchronized
關(guān)鍵字 synchronized
用于修飾方法或代碼塊,保證在同一時(shí)刻只有一個(gè)線程能夠執(zhí)行被 synchronized
修飾的代碼。以下是兩種使用方式:
- 修飾方法
public synchronized void test() {// 同步的代碼塊
}
- 修飾代碼塊
public void someMethod() {// 非同步的代碼塊synchronized (lockObject) {// 同步的代碼塊}// 非同步的代碼塊
}
2) volatile
關(guān)鍵字 volatile
用于聲明變量,保證變量的可見(jiàn)性。被 volatile
修飾的變量對(duì)所有線程可見(jiàn),當(dāng)一個(gè)線程修改了這個(gè)變量的值,其他線程能夠立即看到修改后的值。
public class Demo {private volatile int ticketCount = 10;
}
3) 鎖
Java 提供了很多種鎖,常用的有 synchronized
關(guān)鍵字、ReentrantLock
及 Read/Write Lock
等 。
-
ReentrantLock
它支持可重入鎖,允許一個(gè)線程多次獲取同一把鎖。
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class Demo {private final Lock lock = new ReentrantLock();public void test() {lock.lock();try {// 同步的代碼塊} finally {lock.unlock();}} }
ReentrantLock
提供了比synchronized
更豐富的功能,如可中斷鎖、公平鎖、定時(shí)鎖等 -
Read/Write Lock
ReadWriteLock
接口定義了讀寫(xiě)鎖,它包含兩個(gè)鎖,一個(gè)用于讀操作,一個(gè)用于寫(xiě)操作。讀寫(xiě)鎖允許多個(gè)線程同時(shí)讀取共享資源,但只允許一個(gè)線程進(jìn)行寫(xiě)操作。ReentrantReadWriteLock
是ReadWriteLock
的一個(gè)實(shí)現(xiàn)類import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;public class Demo {private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();public void read() {readWriteLock.readLock().lock();try {// 讀取共享資源的操作} finally {readWriteLock.readLock().unlock();}}public void write() {readWriteLock.writeLock().lock();try {// 修改共享資源的操作} finally {readWriteLock.writeLock().unlock();}} }
讀寫(xiě)鎖適用于讀操作遠(yuǎn)遠(yuǎn)多于寫(xiě)操作的場(chǎng)景,可以提高并發(fā)性
-
StampedLock
它是一種讀寫(xiě)鎖的變種,提供了樂(lè)觀讀鎖,可以在讀多寫(xiě)少的場(chǎng)景中提供更好的性能
import java.util.concurrent.locks.StampedLock;public class Demo {private final StampedLock stampedLock = new StampedLock();public void read() {long stamp = stampedLock.tryOptimisticRead();// 樂(lè)觀讀操作if (!stampedLock.validate(stamp)) {// 有寫(xiě)操作發(fā)生,轉(zhuǎn)為悲觀讀stamp = stampedLock.readLock();try {// 悲觀讀操作} finally {stampedLock.unlockRead(stamp);}}}public void write() {long stamp = stampedLock.writeLock();try {// 寫(xiě)操作} finally {stampedLock.unlockWrite(stamp);}} }
StampedLock
提供了更細(xì)粒度的控制,并允許在不同的代碼路徑中執(zhí)行不同的操作
總結(jié)
在多線程編程中,確保線程安全是至關(guān)重要的!通過(guò)合理使用 synchronized
關(guān)鍵字、volatile
關(guān)鍵字以及 ReentrantLock
等鎖機(jī)制,可以有效地保護(hù)共享資源,避免數(shù)據(jù)不一致和競(jìng)態(tài)條件等問(wèn)題。合理的同步機(jī)制不僅能夠提高程序的性能,還能夠確保程序的正確性。在實(shí)際開(kāi)發(fā)中,根據(jù)具體場(chǎng)景選擇合適的同步和鎖機(jī)制是編寫(xiě)高效、安全多線程代碼的關(guān)鍵。