Kotlin の読み取りと書き込みの分離 CopyOnWriteArrayList

Kotlin の読み取りと書き込みの分離 CopyOnWriteArrayList

読み取りと書き込みの分離、読み取りと読み取りの共有、書き込みと書き込みの相互排他、読み取りと書き込みの相互排他、および書き込みのためのコピーオンライト (COW) の考えに基づいて設計されたスレッドセーフな ArrayList バリアント。相互排他を読みます。読み取り時にロック同期を行わずに直接読み取り、スレッド セーフになります。データの書き込み/削除/変更時にコピーをコピーし、新しいリストのコピーに書き込み/削除/変更を行い、書き込み/削除/変更操作が完了した後にコピーを元のリストに置き換えます。一般に、List の一般的な ConcurrentModificationException 問題を回避するために、通常の ArrayList として使用できます。

利点: より多くの読み取りが必要で、より少ない書き込みが必要なシナリオに適しています。スレッドセーフであり、読み取り時にロックする必要はありません (内部実装はすでにスレッド同期されているため)。読み書き時にブロックされません。

欠点: (1)メモリ使用量の問題。メモリ使用量が多い。書き込み操作中に同じリストがコピーされるため、これは各書き込み操作に必要なメモリ使用量の 2 倍に相当します。

(2)データの一貫性の問題。CopyOnWriteArrayList はデータの最終的な整合性のみを保証でき、リアルタイムの整合性は保証できません。

(3)カウントと書き込み速度の問題。読み取りは高速ですが、書き込み/削除/変更は低速です。

通常の ArrayList を使用すると、マルチスレッド環境では ConcurrentModificationException がスローされます。

import java.util.Collections
import java.util.concurrent.Executors

fun main() {
    val nThreads = 200
    val mExecutorService = Executors.newFixedThreadPool(nThreads)

    var NUM = 0
    var list = Collections.synchronizedList(ArrayList<Int>())
    for (i in 1..nThreads) {
        mExecutorService.execute {
            while (true) {
                Thread.sleep(10)
                list.add(NUM++)

                println("@tid:${Thread.currentThread().threadId()}")
                list.forEachIndexed { index, j ->
                    //println("${list}")
                }
            }
        }
    }

    mExecutorService.shutdown()
}

代わりに CopyOnWriteArrayList を使用すると、正常に動作します。

import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.Executors

fun main() {
    val nThreads = 200
    val mExecutorService = Executors.newFixedThreadPool(nThreads)

    var NUM = 0
    var list = CopyOnWriteArrayList<Int>()
    for (i in 1..nThreads) {
        mExecutorService.execute {
            while (true) {
                Thread.sleep(10)
                list.add(NUM++)

                println("@tid:${Thread.currentThread().threadId()}")
                list.forEachIndexed { index, j ->
                    //println("${list}")
                }
            }
        }
    }

    mExecutorService.shutdown()
}

マルチスレッド環境での ArrayList の読み取りおよび書き込みの安全でない操作は避けてください。

Java スレッド同期リエントラント ロック ReentrantLock と Condition_zhangphil のブログ - CSDN ブログimport java.util.LinkedList;import java.util.Queue;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock ;public class Main { private Queue... https://blog.csdn.net/zhangphil/article/details/92814997 Java スレッド同期ロック ReentrantLock および条件割り込み待機プログラムの前提条件は、met_zhangphil のブログ - CSDN ブログimport java.util.concurrent.TimeUnit;です。 import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;/** * ReentrantLock のロックとロック解除はペアで使用し、同期する必要があるコード ブロックをラップする必要があります。* lock-unlo... https://blog.csdn.net/zhangphil/article/details/92826986 Java スレッドの同期と ReentrantLock のブロック - 条件による wait の置き換え - Notice_reentrantlock と wait Notice_zhangphil のブログ - CSDN ブログimport java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;public class Main { private ReentrantLock lock = new ReentrantLock(false); private 条件 con..._reentrantlock と通知https:// blog.csdn.net/zhangphil/article/details/96360104マルチスレッド同時デッドロックを解決するために ReentrantLock が synchronized を置き換える、デッドロック問題を解決する Java_reentrantlock コード_zhangphil のブログ - CSDN ブログJava 同時マルチスレッド環境、デッドロックを引き起こす最も簡単な方法 シナリオは次のとおりです。 : マルチスレッド内の 1 つのスレッド T_A がロック L1 を保持してロック L2 を申請し、マルチスレッド内の別のスレッド T_B がロック L2 を保持してロック L1 を申請しようとします。スレッドのロック適用操作がブロックされたため、スレッドT_AとスレッドT_Bは所望のロックを正しく取得できず、2つのスレッドはブロックされてデッドロック状態に陥ります。Java スレッド同期ロック ReentrantLock および条件割り込み待機プログラムの前提条件は、met_zhangphil のブログ - CSDN ブログです。デッドロック問題を解決する _reentrantlock コードhttps://blog.csdn.net/zhangphil/article/details/127548507セマフォがマルチスレッド同期を置き換えて同時環境のデッドロックを解決します。Java_semaphore はデッドロックになりますか?_zhangphil のブログ - CSDN ブログ新しい Java スレッド セマフォ: 並列環境で競合リソース制御へのアクセス セマフォは、Java 1.5 から導入された新しい Java スレッドです。Java 同時マルチスレッド環境でデッドロックを引き起こす最も単純なシナリオは、マルチスレッド内の 1 つのスレッド T_A がロック L1 を保持し、ロック L2 を申請して取得しようとする一方で、マルチスレッド内の別のスレッド T_B がロックを保持しているというものです。ロック L2 を取得し、ロック L1 を取得しようとします。スレッドのロック適用操作がブロックされたため、スレッドT_AとスレッドT_Bは所望のロックを正しく取得できず、2つのスレッドはブロックされてデッドロック状態に陥ります。新しい Java スレッド セマフォ: 並列環境で競争力のあるリソース制御にアクセスする_zhangphil のブログ - CSDN ブログ。_semaphore はデッドロックになりますか? https://blog.csdn.net/zhangphil/article/details/127547504新しい Java スレッド セマフォ: 並列環境での競争力のあるリソース制御へのアクセス_zhangphil のブログ - CSDN ブログ新しい Java スレッド セマフォ: 並列環境セマフォはJava 1.5 から導入された Java スレッドの新しいコンテンツ。セマフォは、スレッドの競合リソース アクセス環境下でリソース アクセス制御を実装します。セマフォのライセンスを取得したスレッド タスクのみが、競合するリソースにアクセスできます。例: private void test() { // 多くのスレッドが特定のリソースにアクセスしたいと考えていますが... https://blog.csdn.net/zhangphil/article/details/83410270

Java スレッド プール: ExecutorService、Executors_executorservice thread pool_zhangphil のブログ - CSDN ブログ単純な Java スレッド プールは Executors.newFixedThreadPool (int n) から取得できます。このメソッドは、スレッド容量が n のスレッド プールを返します。次に、ExecutorService の実行によってそれが実行されます。次に例を示します。パッケージ zhangphil.executorservice; インポート java.util.concurrent.ExecutorService; インポート j_executorservice スレッド プールhttps://blog.csdn.net/zhangphil/article/details/43898637

おすすめ

転載: blog.csdn.net/zhangphil/article/details/132165957