java多線程(線程安全,線程同步)
阿新 • • 發佈:2019-01-02
sync com art 線程同步 implement color 子類 ace this
一.線程安全
如果有多個線程在同時運行,而這些線程可能會同時運行這段代碼。程序每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。
通過電影院賣票,演示線程的安全問題:
模擬電影院的賣票過程。本次電影的座位共100個(本場電影只能賣100張票)。模擬電影院的售票窗口,實現多個窗口同時賣這場電影票(多個窗口一起賣這100張票)
需要窗口,采用線程對象來模擬;需要票,Runnable接口子類來模擬
//測試類 public class ThreadDemo { public static void main(String[] args) { //創建票對象Ticket ticket = new Ticket(); //創建3個窗口 Thread t1 = new Thread(ticket, "窗口1"); Thread t2 = new Thread(ticket, "窗口2"); Thread t3 = new Thread(ticket, "窗口3"); t1.start(); t2.start(); t3.start(); } }
//模擬票 public classTicket implements Runnable { //共100票 int ticket = 100; public void run() { //模擬賣票 while(true){ if (ticket > 0) { //模擬選坐的操作 try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ "正在賣票:" + ticket--); } } }
運行結果發現:
①票出現了重復的票
②錯誤的票 0、-1
線程安全問題都是由全局變量及靜態變量引起的。若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。
二.線程同步(線程安全處理Synchronized)
java中提供了線程同步機制,它能夠解決上述的線程安全問題。
線程同步的方式有兩種:
①同步代碼塊
②同步方法
1.同步代碼塊
//同步代碼塊: 在代碼塊聲明上 加上synchronized synchronized (鎖對象) { 可能會產生線程安全問題的代碼 }
同步代碼塊中的鎖對象可以是任意的對象;但多個線程時,要使用同一個鎖對象才能夠保證線程安全。
//使用同步代碼塊,對電影院賣票案例中Ticket類進行如下代碼修改: public class Ticket implements Runnable { //共100票 int ticket = 100; //定義鎖對象 Object lock = new Object(); @Override public void run() { //模擬賣票 while(true){ //同步代碼塊 synchronized (lock){ if (ticket > 0) { //模擬電影選坐的操作 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在賣票:" + ticket--); } } } } }
2.同步方法
//同步方法:在方法聲明上加上synchronized public synchronized void method(){ 可能會產生線程安全問題的代碼 }
同步方法中的鎖對象是 this
//使用同步方法,對電影院賣票案例中Ticket類進行如下代碼修改: public class Ticket implements Runnable { //共100票 int ticket = 100; //定義鎖對象 Object lock = new Object(); @Override public void run() { //模擬賣票 while(true){ //同步方法 method(); } } //同步方法,鎖對象this public synchronized void method(){ if (ticket > 0) { //模擬選坐的操作 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在賣票:" + ticket--); } } }
//靜態同步方法: 在方法聲明上加上static synchronized public static synchronized void method(){ 可能會產生線程安全問題的代碼 }
靜態同步方法中的鎖對象是 類名.class
java多線程(線程安全,線程同步)