本文實例講述了java線程同步操作。分享給大家供大家參考,具體如下:
java線程同步
public class Hello { public static void main(String[] args) { MyRun myRun0 = new MyRun(); new Thread(myRun0, "Thread0").start(); new Thread(myRun0, "Thread1").start(); new Thread(myRun0, "Thread2").start(); }}class MyRun implements Runnable { private int k = 0; @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "**********" + i); k++; if (k <= 3) { if ("Thread0".equals(Thread.currentThread().getName())) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "," + k); } } }}
輸出結果
Thread0**********0
Thread1**********0
Thread2**********0
Thread1,2
Thread2,3
Thread1**********1
Thread2**********1
Thread2**********2
Thread1**********2
Thread0,7
Thread0**********1
Thread0**********2
說明多線程在某些場景是存在問題的,有時候需要線程同步。
同步 synchronized
同步代碼塊,synchronized(obj){}
,obj是一個對象,在這里就相當于一把鎖,表示一旦有進程搶到了這把鎖的鑰匙(就是進入了代碼塊),其他進程將無法進入該鎖的代碼塊(當前代碼塊其他進程一定是進不來了,其他地方的代碼塊如果也是用了這把鎖,同樣進不去),只有代碼塊執行完,釋放鎖后,所有進程再重新搶鑰匙。
注意,上同一把鎖的代碼塊都會被鎖住,這些代碼塊可能寫在不同方法不同位置上。
被同步代碼塊包住的代碼多個線程只能順次進入。
synchronized (this) { k++; if (k <= 3) { if ("Thread0".equals(Thread.currentThread().getName())) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "," + k); }}
this
表示當前對象,這里考慮的只是運行這個方法,不涉及其它類也不涉及這個類的其它地方需要同步問題,所以用this
也是可以的。k增加和輸出一個流程內只能有一個線程在訪問,所以可以得到想要的輸出結果
輸出結果
Thread0**********0
Thread1**********0
Thread2**********0
Thread0,1
Thread0**********1
Thread2,2
Thread2**********1
Thread1,3
Thread1**********1
Thread0**********2
Thread2**********2
Thread1**********2
對方法進行同步,如果存在多線程,每個線程順次訪問該方法
注意,如果一個類里面存在多個同步方法,那么這些同步方法的鎖是一個,都是當前對象,所以不同線程想同時訪問同一對象的不同方法也是不行的,因為這些方法都上了同一把鎖,但是鑰匙只有一把,只能一個線程持有。
@Overridepublic synchronized void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "**********" + i); k++; if (k <= 3) { if ("Thread0".equals(Thread.currentThread().getName())) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "," + k); } }}
輸出結果
Thread0**********0
Thread0,1
Thread0**********1
Thread0,2
Thread0**********2
Thread0,3
Thread2**********0
Thread2**********1
Thread2**********2
Thread1**********0
Thread1**********1
Thread1**********2
死鎖
public class Hello { public static void main(String[] args) { A a = new A(); B b = new B(); new Thread(new MyRun(a,b)).start(); new Thread(new MyRun1(a,b)).start(); }}class MyRun implements Runnable{ private A a; private B b; public MyRun(A a, B b) { this.a = a; this.b = b; } @Override public void run(){ a.say(b); }}class MyRun1 implements Runnable { private A a; private B b; public MyRun1(A a, B b) { this.a = a; this.b = b; } @Override public void run() { b.say(a); }}class A{ public synchronized void say(B b){ System.out.println("A要知道B的信息"); b.info(); } public synchronized void info(){ System.out.println("這是A"); }}class B{ public synchronized void say(A a){ System.out.println("B要知道A的信息"); a.info(); } public synchronized void info(){ System.out.println("這是B"); }}
如果兩個線程同時進入了兩個say方法,就是出現死鎖。
關鍵點在于一個對象的多個同步方法具有相同的鎖,都是當前對象。也就是x線程在訪問a對象的say方法過程中,y線程是無法訪問a對象的info方法的,因為開鎖的鑰匙已經被x線程搶占了。
上面的程序,如果線程x,y同時進入了兩個say方法,a對象同步方法的鎖被線程x搶占,b對象同步方法的鎖被線程y搶占,此時線程x無法訪問b對象的同步方法,線程y無法訪問a對象的同步方法。代碼中恰好想要訪問,所以就出現死鎖了。
希望本文所述對大家java程序設計有所幫助。
新聞熱點
疑難解答
圖片精選