国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - java synchronized關(guān)鍵字的用法

java synchronized關(guān)鍵字的用法

2020-04-24 12:20wulei JAVA教程

synchronized關(guān)鍵字我們大家都知道是線程同步關(guān)鍵字.總結(jié)一下日常的使用方法,還有一個(gè)坑.

0.先導(dǎo)的問題代碼

    下面的代碼演示了一個(gè)計(jì)數(shù)器,兩個(gè)線程同時(shí)對(duì)i進(jìn)行累加的操作,各執(zhí)行1000000次.我們期望的結(jié)果肯定是i=2000000.但是我們多次執(zhí)行以后,會(huì)發(fā)現(xiàn)i的值永遠(yuǎn)小于2000000.這是因?yàn)?兩個(gè)線程同時(shí)對(duì)i進(jìn)行寫入的時(shí)候,其中一個(gè)線程的結(jié)果會(huì)覆蓋另外一個(gè).

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class AccountingSync implements Runnable {
  static int i = 0;
  public void increase() {
    i++;
  }
 
  @Override
  public void run() {
    for (int j = 0; j < 1000000; j++) {
      increase();
    }
  }
 
  public static void main(String[] args) throws InterruptedException {
    AccountingSync accountingSync = new AccountingSync();
 
    Thread t1 = new Thread(accountingSync);
    Thread t2 = new Thread(accountingSync);
 
    t1.start();
    t2.start();
 
    t1.join();
    t2.join();
 
    System.out.println(i);
  }
}

    要從根本上解決這個(gè)問題,我們必須保證多個(gè)線程在對(duì)i進(jìn)行操作的時(shí)候,要完全的同步.也就是說到A線程對(duì)i進(jìn)行寫入的時(shí)候,B線程不僅不可以寫入,連讀取都不可以.

1.synchronized關(guān)鍵字的作用

    關(guān)鍵字synchronized的作用其實(shí)就是實(shí)現(xiàn)線程間的同步.它的工作就是對(duì)同步的代碼進(jìn)行加鎖,使得每一次,只能有一個(gè)線程進(jìn)入同步塊,從而保證線程間的安全性.就像上面的代碼中,i++的操作只能同時(shí)又一個(gè)線程在執(zhí)行.

2.synchronized關(guān)鍵字的用法

指定對(duì)象加鎖:對(duì)給定的對(duì)象進(jìn)行加鎖,進(jìn)入同步代碼塊要獲得給定對(duì)象的鎖

直接作用于實(shí)例方法:相當(dāng)于對(duì)當(dāng)前實(shí)例加鎖,進(jìn)入同步代碼塊要獲得當(dāng)前實(shí)例的鎖(這要求創(chuàng)建Thread的時(shí)候,要用同一個(gè)Runnable的實(shí)例才可以)

直接作用于靜態(tài)方法:相當(dāng)于給當(dāng)前類加鎖,進(jìn)入同步代碼塊前要獲得當(dāng)前類的鎖

2.1指定對(duì)象加鎖

    下面的代碼,將synchronized作用于一個(gè)給定的對(duì)象.這里有一個(gè)注意的,給定對(duì)象一定要是static的,否則我們每次new一個(gè)線程出來,彼此并不共享該對(duì)象,加鎖的意義也就不存在了.

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class AccountingSync implements Runnable {
  final static Object OBJECT = new Object();
  
  static int i = 0;
  public void increase() {
    i++;
  }
  
  @Override
  public void run() {
    for (int j = 0; j < 1000000; j++) {
      synchronized (OBJECT) {
        increase();
      }
    }
  }
  
  public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(new AccountingSync());
    Thread t2 = new Thread(new AccountingSync());
  
    t1.start();
    t2.start();
  
    t1.join();
    t2.join();
  
    System.out.println(i);
  }
}
2.2直接作用于實(shí)例方法

 

    synchronized關(guān)鍵字作用于實(shí)例方法,就是說在進(jìn)入increase()方法之前,線程必須獲得當(dāng)前實(shí)例的鎖.這就要求我們,在創(chuàng)建Thread實(shí)例的時(shí)候,要使用同一個(gè)Runnable的對(duì)象實(shí)例.否則,線程的鎖都不在同一個(gè)實(shí)例上面,無從去談加鎖/同步的問題了.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class AccountingSync implements Runnable {
  static int i = 0;
  public synchronized void increase() {
    i++;
  }
 
  @Override
  public void run() {
    for (int j = 0; j < 1000000; j++) {
      increase();
    }
  }
 
  public static void main(String[] args) throws InterruptedException {
    AccountingSync accountingSync = new AccountingSync();
 
    Thread t1 = new Thread(accountingSync);
    Thread t2 = new Thread(accountingSync);
 
    t1.start();
    t2.start();
 
    t1.join();
    t2.join();
 
    System.out.println(i);
  }
}

    請(qǐng)注意main方法的前三行,說明關(guān)鍵字作用于實(shí)例方法上的正確用法.

2.3直接作用于靜態(tài)方法

    將synchronized關(guān)鍵字作用在static方法上,就不用像上面的例子中,兩個(gè)線程要指向同一個(gè)Runnable方法.因?yàn)榉椒▔K需要請(qǐng)求的是當(dāng)前類的鎖,而不是當(dāng)前實(shí)例,線程間還是可以正確同步的.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class AccountingSync implements Runnable {
  static int i = 0;
  public static synchronized void increase() {
    i++;
  }
 
  @Override
  public void run() {
    for (int j = 0; j < 1000000; j++) {
      increase();
    }
  }
 
  public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(new AccountingSync());
    Thread t2 = new Thread(new AccountingSync());
 
    t1.start();
    t2.start();
 
    t1.join();
    t2.join();
 
    System.out.println(i);
  }
}

3.錯(cuò)誤的加鎖

    從上面的例子里,我們知道,如果我們需要一個(gè)計(jì)數(shù)器應(yīng)用,為了保證數(shù)據(jù)的正確性,我們自然會(huì)需要對(duì)計(jì)數(shù)器加鎖,因此,我們可能會(huì)寫出下面的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class BadLockOnInteger implements Runnable {
  static Integer i = 0;
  @Override
  public void run() {
    for (int j = 0; j < 1000000; j++) {
      synchronized (i) {
        i++;
      }
    }
  }
 
  public static void main(String[] args) throws InterruptedException {
    BadLockOnInteger badLockOnInteger = new BadLockOnInteger();
 
    Thread t1 = new Thread(badLockOnInteger);
    Thread t2 = new Thread(badLockOnInteger);
 
    t1.start();
    t2.start();
 
    t1.join();
    t2.join();
 
    System.out.println(i);
  }
}

    當(dāng)我們運(yùn)行上面代碼的時(shí)候,會(huì)發(fā)現(xiàn)輸出的i很小.這說明線程并沒有安全.

    要解釋這個(gè)問題,要從Integer說起:在Java中,Integer屬于不變對(duì)象,和String一樣,對(duì)象一旦被創(chuàng)建,就不能被修改了.如果你有一個(gè)Integer=1,那么它就永遠(yuǎn)都是1.如果你想讓這個(gè)對(duì)象=2呢?只能重新創(chuàng)建一個(gè)Integer.每次i++之后,相當(dāng)于調(diào)用了Integer的valueOf方法,我們看一下Integer的valueOf方法的源碼:

?
1
2
3
4
5
public static Integer valueOf(int i) {
  if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
  return new Integer(i);
}

    Integer.valueOf()實(shí)際上是一個(gè)工廠方法,他會(huì)傾向于返回一個(gè)新的Integer對(duì)象,并把值重新復(fù)制給i;

    所以,我們就知道問題所在的原因,由于在多個(gè)線程之間,由于i++之后,i都指向了一個(gè)新的對(duì)象,所以線程每次加鎖可能都加載了不同的對(duì)象實(shí)例上面.解決方法很簡(jiǎn)單,使用上面的3種synchronize的方法之一就可以解決了.

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: baoyu123成人免费看视频 | 99亚洲伊人久久精品影院 | 日韩激情一区二区 | 操久久| 欧美视频一区二区 | av一级久久 | av在线中文 | 国产精品成人在线视频 | 天堂网中文在线 | 久久国产日韩 | 91久久精品国产91久久 | 久久久久久亚洲 | 成人免费一区二区三区视频网站 | 日韩高清在线一区 | av黄色影院 | 91社区在线播放 | 黄色一级片免费 | 欧美日韩一区二区在线 | 欧美亚洲高清 | 亚洲自拍偷拍一区 | 黄色一级片黄色一级片 | 国内精品一区二区 | 午夜私人视频 | 毛片xxx | 国产精品久久久久久久久免费高清 | 国产精品成人3p一区二区三区 | 99在线免费视频 | 国产精品一区二区三区四区 | 美女天堂 | 欧美黑人一级爽快片淫片高清 | 日韩一区二区三区在线 | 九九在线视频 | 日日骚视频 | 国产精品美女久久久久久久久久久 | 亚洲aaa在线观看 | 日韩成人在线视频 | 中文字幕www.| 欧美一级片aaa | 中文av在线播放 | 亚洲精品一区二区三区在线 | 成人高清网站 |