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

歡迎訪問 生活随笔!

生活随笔

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

java

Java线程(七):锁对象Lock-同步问题更完美的处理方式 .

發布時間:2025/3/8 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java线程(七):锁对象Lock-同步问题更完美的处理方式 . 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ? Lock是java.util.concurrent.locks包下的接口,Lock 實現提供了比使用synchronized 方法和語句可獲得的更廣泛的鎖定操作,它能以更優雅的方式處理線程同步問題,我們拿Java線程(二)中的一個例子簡單的實現一下和sychronized一樣的效果,代碼如下:

?

[java] view plaincopyprint?
  • public?class?LockTest?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????final?Outputter1?output?=?new?Outputter1();??
  • ????????new?Thread()?{??
  • ????????????public?void?run()?{??
  • ????????????????output.output("zhangsan");??
  • ????????????};??
  • ????????}.start();????????
  • ????????new?Thread()?{??
  • ????????????public?void?run()?{??
  • ????????????????output.output("lisi");??
  • ????????????};??
  • ????????}.start();??
  • ????}??
  • }??
  • class?Outputter1?{??
  • ????private?Lock?lock?=?new?ReentrantLock();//?鎖對象 ??
  • ????public?void?output(String?name)?{??
  • ????????//?TODO?線程輸出方法 ??
  • ????????lock.lock();//?得到鎖 ??
  • ????????try?{??
  • ????????????for(int?i?=?0;?i?<?name.length();?i++)?{??
  • ????????????????System.out.print(name.charAt(i));??
  • ????????????}??
  • ????????}?finally?{??
  • ????????????lock.unlock();//?釋放鎖 ??
  • ????????}??
  • ????}??
  • }??
  • public class LockTest {public static void main(String[] args) {final Outputter1 output = new Outputter1();new Thread() {public void run() {output.output("zhangsan");};}.start(); new Thread() {public void run() {output.output("lisi");};}.start();} } class Outputter1 {private Lock lock = new ReentrantLock();// 鎖對象public void output(String name) {// TODO 線程輸出方法lock.lock();// 得到鎖try {for(int i = 0; i < name.length(); i++) {System.out.print(name.charAt(i));}} finally {lock.unlock();// 釋放鎖}} }

    ? ? ? ? 這樣就實現了和sychronized一樣的同步效果,需要注意的是,用sychronized修飾的方法或者語句塊在代碼執行完之后鎖自動釋放,而是用Lock需要我們手動釋放鎖,所以為了保證鎖最終被釋放(發生異常情況),要把互斥區放在try內,釋放鎖放在finally內。

    ?

    ? ? ? ? 如果說這就是Lock,那么它不能成為同步問題更完美的處理方式,下面要介紹的是讀寫鎖(ReadWriteLock),我們會有一種需求,在對數據進行讀寫的時候,為了保證數據的一致性和完整性,需要讀和寫是互斥的,寫和寫是互斥的,但是讀和讀是不需要互斥的,這樣讀和讀不互斥性能更高些,來看一下不考慮互斥情況的代碼原型:

    ?

    [java] view plaincopyprint?
  • public?class?ReadWriteLockTest?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????final?Data?data?=?new?Data();??
  • ????????for?(int?i?=?0;?i?<?3;?i++)?{??
  • ????????????new?Thread(new?Runnable()?{??
  • ????????????????public?void?run()?{??
  • ????????????????????for?(int?j?=?0;?j?<?5;?j++)?{??
  • ????????????????????????data.set(new?Random().nextInt(30));??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}).start();??
  • ????????}?????????
  • ????????for?(int?i?=?0;?i?<?3;?i++)?{??
  • ????????????new?Thread(new?Runnable()?{??
  • ????????????????public?void?run()?{??
  • ????????????????????for?(int?j?=?0;?j?<?5;?j++)?{??
  • ????????????????????????data.get();??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}).start();??
  • ????????}??
  • ????}??
  • }??
  • class?Data?{??????
  • ????private?int?data;//?共享數據???? ??
  • ????public?void?set(int?data)?{??
  • ????????System.out.println(Thread.currentThread().getName()?+?"準備寫入數據");??
  • ????????try?{??
  • ????????????Thread.sleep(20);??
  • ????????}?catch?(InterruptedException?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????????this.data?=?data;??
  • ????????System.out.println(Thread.currentThread().getName()?+?"寫入"?+?this.data);??
  • ????}?????
  • ????public?void?get()?{??
  • ????????System.out.println(Thread.currentThread().getName()?+?"準備讀取數據");??
  • ????????try?{??
  • ????????????Thread.sleep(20);??
  • ????????}?catch?(InterruptedException?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????????System.out.println(Thread.currentThread().getName()?+?"讀取"?+?this.data);??
  • ????}??
  • }??
  • public class ReadWriteLockTest {public static void main(String[] args) {final Data data = new Data();for (int i = 0; i < 3; i++) {new Thread(new Runnable() {public void run() {for (int j = 0; j < 5; j++) {data.set(new Random().nextInt(30));}}}).start();} for (int i = 0; i < 3; i++) {new Thread(new Runnable() {public void run() {for (int j = 0; j < 5; j++) {data.get();}}}).start();}} } class Data { private int data;// 共享數據 public void set(int data) {System.out.println(Thread.currentThread().getName() + "準備寫入數據");try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}this.data = data;System.out.println(Thread.currentThread().getName() + "寫入" + this.data);} public void get() {System.out.println(Thread.currentThread().getName() + "準備讀取數據");try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "讀取" + this.data);} }

    ? ? ? ? 部分輸出結果:

    ?

    ?

    [java] view plaincopyprint?
  • Thread-1準備寫入數據??
  • Thread-3準備讀取數據??
  • Thread-2準備寫入數據??
  • Thread-0準備寫入數據??
  • Thread-4準備讀取數據??
  • Thread-5準備讀取數據??
  • Thread-2寫入12??
  • Thread-4讀取12??
  • Thread-5讀取5??
  • Thread-1寫入12??
  • Thread-1準備寫入數據 Thread-3準備讀取數據 Thread-2準備寫入數據 Thread-0準備寫入數據 Thread-4準備讀取數據 Thread-5準備讀取數據 Thread-2寫入12 Thread-4讀取12 Thread-5讀取5 Thread-1寫入12

    ? ? ? ? 我們要實現寫入和寫入互斥,讀取和寫入互斥,讀取和讀取互斥,在set和get方法加入sychronized修飾符:

    ?

    ?

    [java] view plaincopyprint?
  • public?synchronized?void?set(int?data)?{...}??????
  • public?synchronized?void?get()?{...}??
  • public synchronized void set(int data) {...} public synchronized void get() {...}

    ? ? ? ? 部分輸出結果:
    ?

    [java] view plaincopyprint?
  • Thread-0準備寫入數據??
  • Thread-0寫入9??
  • Thread-5準備讀取數據??
  • Thread-5讀取9??
  • Thread-5準備讀取數據??
  • Thread-5讀取9??
  • Thread-5準備讀取數據??
  • Thread-5讀取9??
  • Thread-5準備讀取數據??
  • Thread-5讀取9??
  • Thread-0準備寫入數據 Thread-0寫入9 Thread-5準備讀取數據 Thread-5讀取9 Thread-5準備讀取數據 Thread-5讀取9 Thread-5準備讀取數據 Thread-5讀取9 Thread-5準備讀取數據 Thread-5讀取9

    ? ? ? ? 我們發現,雖然寫入和寫入互斥了,讀取和寫入也互斥了,但是讀取和讀取之間也互斥了,不能并發執行,效率較低,用讀寫鎖實現代碼如下:

    ?

    ?

    [java] view plaincopyprint?
  • class?Data?{??????
  • ????private?int?data;//?共享數據 ??
  • ????private?ReadWriteLock?rwl?=?new?ReentrantReadWriteLock();?????
  • ????public?void?set(int?data)?{??
  • ????????rwl.writeLock().lock();//?取到寫鎖 ??
  • ????????try?{??
  • ????????????System.out.println(Thread.currentThread().getName()?+?"準備寫入數據");??
  • ????????????try?{??
  • ????????????????Thread.sleep(20);??
  • ????????????}?catch?(InterruptedException?e)?{??
  • ????????????????e.printStackTrace();??
  • ????????????}??
  • ????????????this.data?=?data;??
  • ????????????System.out.println(Thread.currentThread().getName()?+?"寫入"?+?this.data);??
  • ????????}?finally?{??
  • ????????????rwl.writeLock().unlock();//?釋放寫鎖 ??
  • ????????}??
  • ????}?????
  • ????public?void?get()?{??
  • ????????rwl.readLock().lock();//?取到讀鎖 ??
  • ????????try?{??
  • ????????????System.out.println(Thread.currentThread().getName()?+?"準備讀取數據");??
  • ????????????try?{??
  • ????????????????Thread.sleep(20);??
  • ????????????}?catch?(InterruptedException?e)?{??
  • ????????????????e.printStackTrace();??
  • ????????????}??
  • ????????????System.out.println(Thread.currentThread().getName()?+?"讀取"?+?this.data);??
  • ????????}?finally?{??
  • ????????????rwl.readLock().unlock();//?釋放讀鎖 ??
  • ????????}??
  • ????}??
  • }??
  • class Data { private int data;// 共享數據private ReadWriteLock rwl = new ReentrantReadWriteLock(); public void set(int data) {rwl.writeLock().lock();// 取到寫鎖try {System.out.println(Thread.currentThread().getName() + "準備寫入數據");try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}this.data = data;System.out.println(Thread.currentThread().getName() + "寫入" + this.data);} finally {rwl.writeLock().unlock();// 釋放寫鎖}} public void get() {rwl.readLock().lock();// 取到讀鎖try {System.out.println(Thread.currentThread().getName() + "準備讀取數據");try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "讀取" + this.data);} finally {rwl.readLock().unlock();// 釋放讀鎖}} }

    ?

    ? ? ? ? 部分輸出結果:

    ?

    [java] view plaincopyprint?
  • Thread-4準備讀取數據??
  • Thread-3準備讀取數據??
  • Thread-5準備讀取數據??
  • Thread-5讀取18??
  • Thread-4讀取18??
  • Thread-3讀取18??
  • Thread-2準備寫入數據??
  • Thread-2寫入6??
  • Thread-2準備寫入數據??
  • Thread-2寫入10??
  • Thread-1準備寫入數據??
  • Thread-1寫入22??
  • Thread-5準備讀取數據??
  • Thread-4準備讀取數據 Thread-3準備讀取數據 Thread-5準備讀取數據 Thread-5讀取18 Thread-4讀取18 Thread-3讀取18 Thread-2準備寫入數據 Thread-2寫入6 Thread-2準備寫入數據 Thread-2寫入10 Thread-1準備寫入數據 Thread-1寫入22 Thread-5準備讀取數據

    ? ? ? ? 從結果可以看出實現了我們的需求,這只是鎖的基本用法,鎖的機制還需要繼續深入學習。

    轉載于:https://blog.51cto.com/519124/1114616

    總結

    以上是生活随笔為你收集整理的Java线程(七):锁对象Lock-同步问题更完美的处理方式 .的全部內容,希望文章能夠幫你解決所遇到的問題。

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