欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java線程同步操作實(shí)例詳解

 更新時(shí)間:2018年09月06日 11:16:23   作者:shuair  
這篇文章主要介紹了java線程同步操作,結(jié)合實(shí)例形式分析了Java線程同步與鎖機(jī)制相關(guān)原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了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);
      }
    }
  }
}

輸出結(jié)果

Thread0**********0
Thread1**********0
Thread2**********0
Thread1,2
Thread2,3
Thread1**********1
Thread2**********1
Thread2**********2
Thread1**********2
Thread0,7
Thread0**********1
Thread0**********2

說(shuō)明多線程在某些場(chǎng)景是存在問(wèn)題的,有時(shí)候需要線程同步。

同步 synchronized

同步代碼塊,synchronized(obj){},obj是一個(gè)對(duì)象,在這里就相當(dāng)于一把鎖,表示一旦有進(jìn)程搶到了這把鎖的鑰匙(就是進(jìn)入了代碼塊),其他進(jìn)程將無(wú)法進(jìn)入該鎖的代碼塊(當(dāng)前代碼塊其他進(jìn)程一定是進(jìn)不來(lái)了,其他地方的代碼塊如果也是用了這把鎖,同樣進(jìn)不去),只有代碼塊執(zhí)行完,釋放鎖后,所有進(jìn)程再重新?lián)岃€匙。

注意,上同一把鎖的代碼塊都會(huì)被鎖住,這些代碼塊可能寫(xiě)在不同方法不同位置上。

被同步代碼塊包住的代碼多個(gè)線程只能順次進(jìn)入。

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表示當(dāng)前對(duì)象,這里考慮的只是運(yùn)行這個(gè)方法,不涉及其它類(lèi)也不涉及這個(gè)類(lèi)的其它地方需要同步問(wèn)題,所以用this也是可以的。k增加和輸出一個(gè)流程內(nèi)只能有一個(gè)線程在訪問(wèn),所以可以得到想要的輸出結(jié)果

輸出結(jié)果

Thread0**********0
Thread1**********0
Thread2**********0
Thread0,1
Thread0**********1
Thread2,2
Thread2**********1
Thread1,3
Thread1**********1
Thread0**********2
Thread2**********2
Thread1**********2

對(duì)方法進(jìn)行同步,如果存在多線程,每個(gè)線程順次訪問(wèn)該方法

注意,如果一個(gè)類(lèi)里面存在多個(gè)同步方法,那么這些同步方法的鎖是一個(gè),都是當(dāng)前對(duì)象,所以不同線程想同時(shí)訪問(wèn)同一對(duì)象的不同方法也是不行的,因?yàn)檫@些方法都上了同一把鎖,但是鑰匙只有一把,只能一個(gè)線程持有。

@Override
public 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);
    }
  }
}

輸出結(jié)果

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");
  }
}

如果兩個(gè)線程同時(shí)進(jìn)入了兩個(gè)say方法,就是出現(xiàn)死鎖。

關(guān)鍵點(diǎn)在于一個(gè)對(duì)象的多個(gè)同步方法具有相同的鎖,都是當(dāng)前對(duì)象。也就是x線程在訪問(wèn)a對(duì)象的say方法過(guò)程中,y線程是無(wú)法訪問(wèn)a對(duì)象的info方法的,因?yàn)殚_(kāi)鎖的鑰匙已經(jīng)被x線程搶占了。

上面的程序,如果線程x,y同時(shí)進(jìn)入了兩個(gè)say方法,a對(duì)象同步方法的鎖被線程x搶占,b對(duì)象同步方法的鎖被線程y搶占,此時(shí)線程x無(wú)法訪問(wèn)b對(duì)象的同步方法,線程y無(wú)法訪問(wèn)a對(duì)象的同步方法。代碼中恰好想要訪問(wèn),所以就出現(xiàn)死鎖了。

更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Java進(jìn)程與線程操作技巧總結(jié)》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總

希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。

相關(guān)文章

最新評(píng)論