同步代码块解决线程安全
案例:需求現在有100張火車票,有兩個窗口同時搶火車票,請使用多線程模擬搶票效果。
代碼:
package com.learn;class ThreadDemo01 implements Runnable {// 同時多個窗口共享100private static int count = 100;// 存放方法區中private static Object obj = new Object();public void run() {while (count > 0) {try {Thread.sleep(10);sale();} catch (Exception e) {System.out.println(e.getMessage());}}}public void sale() {synchronized(obj){ if (count > 0) {System.out.println(Thread.currentThread().getName() + ",出售" + (100 - count + 1) + "張票");count--;}}} }public class Test0001 {public static void main(String[] args) throws InterruptedException {ThreadDemo01 threadDemo01 = new ThreadDemo01();Thread t1 = new Thread(threadDemo01, "窗口1");Thread t2 = new Thread(threadDemo01, "窗口2");t1.start();t2.start();} }運行結果:
一號窗口和二號窗口同時出售火車第九九張,部分火車票會重復出售。
結論發現,多個線程共享同一個全局成員變量時,做寫的操作可能會發生數據沖突問題。
線程安全解決辦法:
問:如何解決多線程之間線程安全問題
答:使用多線程之間同步synchronized或使用鎖(lock)。
問:為什么使用線程同步或使用鎖能解決線程安全問題呢?
答:將可能會發生數據沖突問題(線程不安全問題),只能讓當前一個線程進行執行。代碼執行完成后釋放鎖,讓后才能讓其他線程進行執行。這樣的話就可以解決線程不安全問題。
問:什么是多線程之間同步
答:當多個線程共享同一個資源,不會受到其他線程的干擾。
問:什么是多線程同步
答:當多個線程共享同一個資源,不會受到其他線程的干擾。
內置的鎖
Java提供了一種內置的鎖機制來支持原子性
每一個Java對象都可以用作一個實現同步的鎖,稱為內置鎖,線程進入同步代碼塊之前自動獲取到鎖,代碼塊執行完成正常退出或代碼塊中拋出異常退出時會釋放掉鎖
內置鎖為互斥鎖,即線程A獲取到鎖后,線程B阻塞直到線程A釋放鎖,線程B才能獲取到同一個鎖
內置鎖使用synchronized關鍵字實現,synchronized關鍵字有兩種用法:
1.修飾需要進行同步的方法(所有訪問狀態變量的方法都必須進行同步),此時充當鎖的對象為調用同步方法的對象
2.同步代碼塊和直接使用synchronized修飾需要同步的方法是一樣的,但是鎖的粒度可以更細,并且充當鎖的對象不一定是this,也可以是其它對象,所以使用起來更加靈活
同步代碼塊synchronized
| 就是將可能會發生線程安全問題的代碼,給包括起來。 synchronized(同一個數據){ ?可能會發生線程沖突問題 } 就是同步代碼塊? synchronized(對象)//這個對象可以為任意對象? {? ????需要被同步的代碼? }? |
對象如同鎖,持有鎖的線程可以在同步中執行?
沒持有鎖的線程即使獲取CPU的執行權,也進不去?
同步的前提:?
1,必須要有兩個或者兩個以上的線程?
2,必須是多個線程使用同一個鎖?
必須保證同步中只能有一個線程在運行?
好處:解決了多線程的安全問題?
弊端:多個線程需要判斷鎖,較為消耗資源、搶鎖的資源。?
?
思考問題?同步方法使用的是什么鎖?
答:同步函數使用this鎖。
證明方式: 一個線程使用同步代碼塊(this明鎖),另一個線程使用同步函數。如果兩個線程搶票不能實現同步,那么會出現數據錯誤。
總結
以上是生活随笔為你收集整理的同步代码块解决线程安全的全部內容,希望文章能夠幫你解決所遇到的問題。