生活随笔
收集整理的這篇文章主要介紹了
线程安全问题解决
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
方式一(同步代碼塊)
synchronized(同步監視器){
//需要被同步的代碼
}
說明:1.操作共享數據的代碼,即為需要被同步的代碼。 -->不能包含代碼多了,也不能包含代碼少了。
2.共享數據:多個線程共同操作的變量。比如:ticket就是共享數據。
3.同步監視器,俗稱:鎖。任何一個類的對象,都可以充當鎖。
要求:多個線程必須要共用同一把鎖。
補充:在實現Runnable接口創建多線程的方式中,我們可以考慮使用this充當同步監視器。
package com.atguigu.java;class Window1 implements Runnable{private int ticket
= 100;
@Overridepublic void run() {
while(true){synchronized (this){if (ticket
> 0) {try {Thread.sleep(100);} catch (InterruptedException e
) {e
.printStackTrace();}System.out
.println(Thread.currentThread().getName() + ":賣票,票號為:" + ticket
);ticket
--;} else {break;}}}}
}public class WindowTest1 {public static void main(String[] args
) {Window1 w
= new Window1();Thread t1
= new Thread(w
);Thread t2
= new Thread(w
);Thread t3
= new Thread(w
);t1
.setName("窗口1");t2
.setName("窗口2");t3
.setName("窗口3");t1
.start();t2
.start();t3
.start();}}class Dog{}
package com.atguigu.java;class Window2 extends Thread{private static int ticket
= 100;private static Object obj
= new Object();@Overridepublic void run() {while(true){
synchronized (Window2.class){
if(ticket
> 0){try {Thread.sleep(100);} catch (InterruptedException e
) {e
.printStackTrace();}System.out
.println(getName() + ":賣票,票號為:" + ticket
);ticket
--;}else{break;}}}}
}public class WindowTest2 {public static void main(String[] args
) {Window2 t1
= new Window2();Window2 t2
= new Window2();Window2 t3
= new Window2();t1
.setName("窗口1");t2
.setName("窗口2");t3
.setName("窗口3");t1
.start();t2
.start();t3
.start();}
}
方式二(同步方法)
如果操作共享數據的代碼完整的聲明在一個方法中,我們不妨將此方法聲明同步的。
關于同步方法的總結:
同步方法仍然涉及到同步監視器,只是不需要我們顯式的聲明。非靜態的同步方法,同步監視器是:this
靜態的同步方法,同步監視器是:當前類本身
package com.atguigu.java;class Window3 implements Runnable {private int ticket
= 100;@Overridepublic void run() {while (true) {show();}}private synchronized void show(){if (ticket
> 0) {try {Thread.sleep(100);} catch (InterruptedException e
) {e
.printStackTrace();}System.out
.println(Thread.currentThread().getName() + ":賣票,票號為:" + ticket
);ticket
--;}}
}public class WindowTest3 {public static void main(String[] args
) {Window3 w
= new Window3();Thread t1
= new Thread(w
);Thread t2
= new Thread(w
);Thread t3
= new Thread(w
);t1
.setName("窗口1");t2
.setName("窗口2");t3
.setName("窗口3");t1
.start();t2
.start();t3
.start();}}
package com.atguigu.java;
class Window4 extends Thread {private static int ticket
= 100;@Overridepublic void run() {while (true) {show();}}private static synchronized void show(){if (ticket
> 0) {try {Thread.sleep(100);} catch (InterruptedException e
) {e
.printStackTrace();}System.out
.println(Thread.currentThread().getName() + ":賣票,票號為:" + ticket
);ticket
--;}}
}public class WindowTest4 {public static void main(String[] args
) {Window4 t1
= new Window4();Window4 t2
= new Window4();Window4 t3
= new Window4();t1
.setName("窗口1");t2
.setName("窗口2");t3
.setName("窗口3");t1
.start();t2
.start();t3
.start();}
}
方式三(Lock鎖)—JDK5.0新增
1. 面試題:
synchronized 與
Lock的異同?相同:二者都可以解決線程安全問題不同:
synchronized機制在執行完相應的同步代碼以后,自動的釋放同步監視器
Lock需要手動的啟動同步(
lock()),同時結束同步也需要手動的實現(
unlock())
2.優先使用順序:
Lock
同步代碼塊(已經進入了方法體,分配了相應資源)
同步方法(在方法體之外)
package com.atguigu.java1;import java.util.concurrent.locks.ReentrantLock;
class Window implements Runnable{private int ticket
= 100;private ReentrantLock lock
= new ReentrantLock();@Overridepublic void run() {while(true){try{lock
.lock();if(ticket
> 0){try {Thread.sleep(100);} catch (InterruptedException e
) {e
.printStackTrace();}System.out
.println(Thread.currentThread().getName() + ":售票,票號為:" + ticket
);ticket
--;}else{break;}}finally {lock
.unlock();}}}
}public class LockTest {public static void main(String[] args
) {Window w
= new Window();Thread t1
= new Thread(w
);Thread t2
= new Thread(w
);Thread t3
= new Thread(w
);t1
.setName("窗口1");t2
.setName("窗口2");t3
.setName("窗口3");t1
.start();t2
.start();t3
.start();}
}
總結
以上是生活随笔為你收集整理的线程安全问题解决的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。