日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java锁机制(一)synchronized

發(fā)布時間:2025/4/14 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java锁机制(一)synchronized 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

進行多線程編程的時候,需要考慮的是線程間的同步問題。對于共享的資源,需要進行互斥的訪問。在Java中可以使用一些手段來達到線程同步的目的:

1. synchronized?

2. ThreadLocal,線程本地變量

3. Java.util.concurrent.Lock

Java中,線程會共享堆上的實例變量以及方法區(qū)的類變量,而棧上的數(shù)據(jù)是私有的,不必進行保護。synchronized方法或synchronized塊將標記一塊監(jiān)視區(qū)域,線程在進入該區(qū)域時,需要獲得對象鎖或類鎖,JVM將自動上鎖。synchronized提供了兩種主要特性:

1. 互斥。互斥是指一次只允許一個線程持有某個特定的鎖,因此可使用該特性實現(xiàn)對共享數(shù)據(jù)的并發(fā)訪問,保證一次只有一個線程能夠使用該共享數(shù)據(jù)。

2.可見性。確保釋放鎖之前對共享數(shù)據(jù)做出的更改對隨后獲得該鎖的另一個線程是可見的。如果不能保證可見性,也就無法保證數(shù)據(jù)正確性,這將引發(fā)嚴重問題。volitail關鍵字同樣保證了這種可見性。

?

在這里,我們將探討synchronized使用時的三種情況:

1. 在對象上使用synchronized

2. 在普通成員方法上使用synchronized

3. 在靜態(tài)成員方法上使用synchronized

這三種線程同步的表現(xiàn)有何不同?

下面通過三段示例代碼來演示這三種情況。這里模擬線程報數(shù)的場景。

情況一:在普通成員函數(shù)上使用synchronized

public class MyThread extends Thread {public static void main(String[] args) throws Exception {for (int i = 1; i < 100; i++) {MyThread t = new MyThread();t.setName("Thread="+i);t.start();Thread.sleep(100);}}@Overridepublic synchronized void run() {for (int i = 1; i < 10000; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}} }

?

對一個成員函數(shù)使用synchronized進行加鎖,所獲取的鎖,是方法所在對象本身的對象鎖。在這里,每個線程都以自身的對象作為對象鎖,要對線程進行同步,要求鎖對象必須唯一,所以這里多個線程間同步失敗。

情況二:在對象上使用synchronized

這里在類中增加一個成員變量lock,在該變量上使用synchronized:

?

public class MyThread1 extends Thread {private String lock;public MyThread1(String lock) {this.lock = lock;}public static void main(String[] args) throws Exception {String lock = new String("lock");for (int i = 1; i < 100; i++) {Thread t = new MyThread1(lock);t.setName("Thread=" + i);t.start();Thread.sleep(100);}}@Overridepublic void run() {synchronized (lock) {for (int i = 1; i < 10000; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}}} }

?

100個線程在創(chuàng)建的時候,都傳遞了同一個lock對象(在main中創(chuàng)建的)去初始化線程類成員lock,因此,這100個線程都在同一個lock對象上進行synchronized同步。因此線程同步成功。

情況三:在靜態(tài)成員函數(shù)上使用synchronized

public class MyThread2 extends Thread {public static void main(String[] args) throws Exception {for (int i = 1; i < 10; i++) {Thread t = new MyThread2();t.setName("Thread=" + i);t.start();Thread.sleep(10);}}public static synchronized void func() {for (int i = 1; i < 100; i++) {System.out.println(Thread.currentThread().getName() + ":" + i);}}@Overridepublic void run() {func();} }

這種情況下,線程獲得的鎖是對象鎖,而對象鎖是唯一的,因此多個進程間也能同步成功。

補充:

1. 慎用字符串常量做同步對象,因為JVM內部會把常量字符串轉換成同一個對象,同理的,基本數(shù)據(jù)除了Float和Double外,也有緩存對象[-128,127].

2. synchronized方法繼承問題:1. 子類會繼承父類的synchronized方法。2. 如果子類重寫了父類的synchronized方法,必須也加上synchronized關鍵字,否則子類中的方法將變成非同步的。 3. 同一個子類對象中,子類的synchronized方法父類的synchronized方法使用的是同一個臨界區(qū)。?

(完)

  

轉載于:https://www.cnblogs.com/QG-whz/p/8342276.html

總結

以上是生活随笔為你收集整理的Java锁机制(一)synchronized的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。