1. 程式人生 > >同一資源多執行緒併發訪問時的完整性

同一資源多執行緒併發訪問時的完整性

 

  在Java中一共有四種方法支援同步,其中前三個是同步方法,一個是管道方法。管道方法不建議使用,阻塞佇列方法在問題4已有描述,現只提供前兩種實現方法。

 

- wait()/notify()方法

 

- await()/signal()方法

 

- BlockingQueue阻塞佇列方法

 

- PipedInputStream/PipedOutputStream

 

  一、生產者類:

 

```

 

public class Producer extends Thread { // 每次生產的產品數量

 

private int num;

 

// 所在放置的倉庫

 

private Storage storage;

 

// 建構函式,設定倉庫

 

public Producer(Storage storage) {

 

this.storage = storage;

 

}

 

// 執行緒run函式

 

public void run() {

 

produce(num);

 

}

 

// 呼叫倉庫Storage的生產函式

 

public void produce(int num) {

 

storage.produce(num);

 

}

 

public int getNum() {

 

return num;

 

}

 

public void setNum(int num) {

 

this.num = num;

 

}

 

public Storage getStorage() {

 

return storage;

 

}

 

public void setStorage(Storage storage) {

 

this.storage = storage;

 

}

 

}

 

```

 

  二、消費者類:

 

```

 

public class Consumer extends Thread { // 每次消費的產品數量

 

private int num;

 

// 所在放置的倉庫

 

private Storage storage;

 

// 建構函式,設定倉庫

 

public Consumer(Storage storage) {

 

this.storage = storage;

 

}

 

// 執行緒run函式

 

public void run() {

 

consume(num);

 

}

 

// 呼叫倉庫Storage的生產函式

 

public void consume(int num) {

 

storage.consume(num);

 

}

 

// get/set方法

 

public int getNum() {

 

return num;

 

}

 

public void setNum(int num) {

 

this.num = num;

 

}

 

public Storage getStorage() {

 

return storage;

 

}

 

public void setStorage(Storage storage) {

 

this.storage = storage;

 

}

 

}

 

```

 

  倉庫類:(wait()/notify()方法)

 

```

 

public class Storage { // 倉庫最大儲存量

 

private final int MAX_SIZE = 100;

 

// 倉庫儲存的載體

 

private LinkedList list = new LinkedList();

 

// 生產num個產品

 

public void produce(int num) {

 

// 同步程式碼段

 

synchronized (list) {

 

// 如果倉庫剩餘容量不足

 

while (list.size() + num > MAX_SIZE) {

 

System.out.print("【要生產的產品數量】:" + num);

 

System.out.println(" 【庫存量】:" + list.size() + " 暫時不能執行生產任務!");

 

try {

 

list.wait();// 由於條件不滿足,生產阻塞

 

} catch (InterruptedException e) {

 

e.printStackTrace();

 

}

 

}

 

// 生產條件滿足情況下,生產num個產品

 

for (int i = 1; i <= num; ++i) {

 

list.add(new Object());

 

}

 

System.out.print("【已經生產產品數】:" + num);

 

System.out.println(" 【現倉儲量為】:" + list.size());

 

list.notifyAll();

 

}

 

}

 

// 消費num個產品

 

public void consume(int num) {

 

// 同步程式碼段

 

synchronized (list) {

 

// 如果倉庫儲存量不足

 

while (list.size() < num) {

 

System.out.print("【要消費的產品數量】:" + num);

 

System.out.println(" 【庫存量】:" + list.size() + " 暫時不能執行生產任務!");

 

try {

 

// 由於條件不滿足,消費阻塞

 

list.wait();

 

} catch (InterruptedException e) {

 

e.printStackTrace();

 

}

 

}

 

// 消費條件滿足情況下,消費num個產品

 

for (int i = 1; i <= num; ++i) {

 

list.remove();

 

}

 

System.out.print("【已經消費產品數】:" + num);

 

System.out.println(" 【現倉儲)量為】:" + list.size());

 

list.notifyAll();

 

}

 

}

 

// get/set方法

 

public LinkedList getList() {

 

return list;

 

}

 

public void setList(LinkedList list) {

 

this.list = list;

 

}

 

public int getMAX_SIZE() {

 

return MAX_SIZE;

 

}

 

}

 

```

 

  倉庫類:(await()/signal()方法)

 

```

 

public class Storage { // 倉庫最大儲存量

 

// 倉庫最大儲存量

 

private final int MAX_SIZE = 100;

 

// 倉庫儲存的載體

 

private LinkedList list = new LinkedList();

 

// 鎖

 

private final Lock lock = new ReentrantLock();

 

// 倉庫滿的條件變數

 

private final Condition full = lock.newCondition();

 

// 倉庫空的條件變數

 

private final Condition empty = lock.newCondition();

 

// 生產num個產品

 

public void produce(int num) {

 

// 獲得鎖

 

lock.lock();

 

// 如果倉庫剩餘容量不足

 

while (list.size() + num > MAX_SIZE) {

 

System.out.print("【要生產的產品數量】:" + num);

 

System.out.println(" 【庫存量】:" + list.size() + " 暫時不能執行生產任務!");

 

try {

 

// 由於條件不滿足,生產阻塞

 

full.await();

 

} catch (InterruptedException e) {

 

e.printStackTrace();

 

}

 

}

 

// 生產條件滿足情況下,生產num個產品

 

for (int i = 1; i <= num; ++i) {

 

list.add(new Object());

 

}

 

System.out.print("【已經生產產品數】:" + num);

 

System.out.println(" 【現倉儲量為】:" + list.size());

 

// 喚醒其他所有執行緒

 

full.signalAll();

 

empty.signalAll();

 

// 釋放鎖

 

lock.unlock();

 

}

 

// 消費num個產品

 

public void consume(int num) {

 

// 獲得鎖

 

lock.lock();

 

// 如果倉庫儲存量不足

 

while (list.size() < num) {

 

System.out.print("【要消費的產品數量】:" + num);

 

System.out.println(" 【庫存量】:" + list.size() + " 暫時不能執行生產任務!");

 

try {

 

// 由於條件不滿足,消費阻塞

 

empty.await();

 

} catch (InterruptedException e) {

 

e.printStackTrace();

 

}

 

}

 

// 消費條件滿足情況下,消費num個產品

 

for (int i = 1; i <= num; ++i) {

 

list.remove();

 

}

 

System.out.print("【已經消費產品數】:" + num);

 

System.out.println(" 【現倉儲)量為】:" + list.size());

 

// 喚醒其他所有執行緒

 

full.signalAll();

 

empty.signalAll();

 

// 釋放鎖

 

lock.unlock();

 

}

 

// set/get方法

 

public int getMAX_SIZE() {

 

return MAX_SIZE;

 

}

 

public LinkedList getList() {

 

return list;

 

}

 

public void setList(LinkedList list) {

 

this.list = list;

 

}

 

}

 

相關推薦

同一資源執行併發訪問完整性

    在Java中一共有四種方法支援同步,其中前三個是同步方法,一個是管道方法。管道方法不建議使用,阻塞佇列方法在問題4已有描述,現只提供前兩種實現方法。   - wait()/notify()方法   - await()/signal()方法  

執行併發訪問的安全性問題】

【多執行緒併發訪問的安全性問題】 今天重新溫習了一下多執行緒併發訪問的問題,加強下記憶,決定寫一些東西記錄下來。【持續更新】 多執行緒併發訪問的安全性問題 首先要知道的是:多執行緒安全性問題產生的原因是什麼? 多執行緒併發訪問是指當多個執行緒無序的訪問同一個共享資源時,這個

Android SQLite使用詳解和執行併發訪問

Android中資料持久化技術包括檔案儲存、SharedPreferences以及資料庫儲存,對於大量複雜的關係型資料,資料庫無疑是最合適的選擇。SQLite是一個輕量級的關係型資料庫,運算速度快,佔用資源少,適合在移動裝置上使用。SQLite不僅支援SQL語法,還遵循資料庫

執行併發訪問可能出現的崩潰問題

出現這個崩潰的現象是, 進入一個介面時,該介面會同時發起三個非同步請求操作。每個操作在發起資料請求時,都可能會調某一方法進行存取某一屬性值。 如屬性comName; 該屬性宣告為:@Property (nonatomic, strong) NSString *comName

自己在之前做兩個專案中遇到執行併發訪問如何解決的一個簡單demo程式

package com.geloin.main; public class TestMoreThread { public static void main(String[] args) { final test t0=new test(); final te

Java併發程式設計(03):執行併發訪問,同步控制

本文原始碼:[GitHub·點這裡](https://github.com/cicadasmile/java-base-parent) || [GitEE·點這裡](https://gitee.com/cicadasmile/java-base-parent) # 一、併發問題 多執行緒學習的時候,要面

執行互斥訪問資源的Demo

這個程式因為把執行緒的建立寫在了建構函式裡,不用顯式啟動執行緒,也因此有些臃腫。 #include <iostream> #include <stdlib.h> #include <thread> #include <mutex> #include

jmeter執行併發,區域性變數和全域性變數的區別

1. 業務場景5個使用者登入系統,需要將登入介面A返回的token作為介面B的入參。介面B設定集合點,同時請求後臺介面。2. 指令碼2.1  目錄結構                2.2  多個使用者資訊獲取                採用csv檔案儲存使用者資訊   

【小家Java】Future、FutureTask、CompletionService、CompletableFuture解決執行併發中歸集問題的效率對比

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

面試題之——執行併發面試題

1) 什麼是執行緒?   執行緒是作業系統能夠進行運算排程的最小單位,它被包含在程序之中,是程序中的實際運作單位。程式設計師可以通過它進行多處理器程式設計,你可以使用多執行緒對運算密集型任務提速。比如,如果一個執行緒完成一個任務要100毫秒,那麼用十個執行緒完成改任務只需10毫秒。Java在語言層面對多執行

網際網路架構執行併發程式設計高階教程(上)

#基礎篇幅:執行緒基礎知識、併發安全性、JDK鎖相關知識、執行緒間的通訊機制、JDK提供的原子類、併發容器、執行緒池相關知識點  #高階篇幅:ReentrantLock原始碼分析、對比兩者原始碼,更加深入理解讀寫鎖,JAVA記憶體模型、先行發生原則、指令重排序 #環境說明:idea、ja

實驗5 結果不唯一的執行併發執行例項 操作指導

實驗5  結果不唯一的多執行緒併發執行例項 操作指導 變數及函式說明   pthread_t 型別定義:typedef unsigned long int pthread_t; //come from /usr/include/bits/

JAVA學習筆記(併發程式設計 - 玖)- 執行併發拓展

文章目錄 死鎖 概念 產生條件 例子 併發最佳實踐 Spring與執行緒安全 死鎖 概念 死鎖是指兩個或兩個以上的程序在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象

Jmeter測試執行併發請求 與 OSS 物件儲存 測試報告

  1.測試資料夾包含特殊字元 出現重大BUG問題:  \\ 和 /  運用到Key中  資料夾不能刪除 解決方案:應該在根源上傳之前進行   規避  出現這樣的字元在一起 直接丟擲錯誤資訊給使用者 2.測

Java執行-併發執行

執行緒池有了解嗎? 答: java.util.concurrent.ThreadPoolExecutor 類就是一個執行緒池。客戶端呼叫ThreadPoolExecutor.submit(Runnable task) 提交任務,執行緒池內部維護的工作者執行緒的數量就是該執行緒池的執行

Java執行-併發之synchronized 關鍵字

synchronized 關鍵字 答: 底層實現: 進入時,執行 monitorenter,將計數器 +1,釋放鎖 monitorexit 時,計數器 -1 當一個執行緒判斷到計數器為 0 時,則當前鎖空閒,可以佔用;反之,當前執行緒進入等待狀態 含義

Java執行-併發之sleep() 和 wait(n) 、 wait() 的區別

sleep() 和 wait(n) 、 wait() 的區別 答: sleep 方法:是 Thread 類的靜態方法,當前執行緒將睡眠 n 毫秒,執行緒進入阻塞狀態。當睡眠時間到了,會接觸阻塞,進入可執行狀態,等待 CPU 的到來。睡眠不釋放鎖(如果有的話) wai

Java執行-併發執行產生死鎖的4個必要條件?如何避免死鎖?

多執行緒產生死鎖的4個必要條件? 答: 互斥條件:一個資源每次只能被一個執行緒使用 請求與保持條件:一個執行緒因請求資源而阻塞時,對已獲得的資源保持不放 不剝奪條件:程序已經獲得的資源,在未使用完之前,不能強行剝奪 迴圈等待條件:若干執行緒之間形成一種頭

Java執行-併發執行和程序的區別

執行緒和程序的區別 答: 程序是一個“執行中的程式”,是系統進行資源分配和排程的一個獨立單位 執行緒是程序的一個實體,一個程序中擁有多個執行緒,執行緒之間共享地址空間和其他資源(所以通訊和同步等操作執行緒比程序更加容易) 執行緒上下文的切換比程序上下文切換要快

Java執行-併發之如何制定執行執行順序?

文章目錄 如何讓10個執行緒按照順序列印0123456789? 程式碼如下: 1.建立一個鎖物件類 2.建立一個執行緒類 3.測試類 如何讓10個執行緒按照順序列印012