Rumah Java javaTutorial Java 竞态条件和临界段

Java 竞态条件和临界段

Feb 28, 2017 am 10:35 AM

一个竞态条件是一个特殊的条件,可能发生在一个临界部分的内部(critical section)。一个临界部分是一段正在被多线程执行的代码,以及线程执行的顺序对于临界部分并发执行的结果产生影响。

当多线程执行一个临界段的结果依赖线程执行的顺序可能是不同的,这个临界段包含一个竞态条件。这个竞态条件的词条源于这个线程正在竞速通过这个临界段的暗喻,并且这个竞争的结果影响着执行这个临界段的结果。

这个可能听起来有点复杂,以至于我将会在下面的部分详细阐述关于竞态条件和临界段。


临界段(Critical Sections)

在相同的应用内部运行不止一个线程不会被他自己引起问题。当多个线程访问相同的资源问题就会出现。例如相同的内存(变量,数组,或者对象),系统(数据库,web服务)或者文件。

事实上,如果一个或者多个线程写这些资源的时候问题会出现。让多个线程读取相同的资源是安全的,只要资源不会改变。

这里有一个例子,如果多个线程同事执行可能会失败:


 public class Counter {

     protected long count = 0;

     public void add(long value){
         this.count = this.count + value;
     }
  }
Salin selepas log masuk


想象下如果线程A和B正在执行相同的Counter类的实例的add方法。这里没有办法知道操作系统什么时间会在线程之间切换。add方法中的代码不会被java虚拟机作为单独的原子指令执行。而是作为一系列的更小的指令集执行,跟这个类似:

  1. 从内存中读取this.count值进入寄存器。

  2. 增加value值到寄存器。

  3. 将寄存器中的值写回内存。

观察线程A和B混合执行会发生什么:

       this.count = 0;

   A:  Reads this.count into a register (0)
   B:  Reads this.count into a register (0)
   B:  Adds value 2 to register
   B:  Writes register value (2) back to memory. this.count now equals 2
   A:  Adds value 3 to register
   A:  Writes register value (3) back to memory. this.count now equals 3
Salin selepas log masuk


这两个线程想添加2和3到counter中。因此这两个线程执行完之后的值应该是5。然而,因为这两个线程执行时交叉的,因此结果以不同而结束。

在上面提到的执行顺序的例子中,两个线程都从内存中读取到0这个值。然后他们添加他们各自的值,2和3到那个值中去,然后把这个结果写回到内存中。代替5,在this.count中留下的值将会是最后的那个线程写给他的那个值。在上面的例子中是线程A,但是他也可能是线程B。

在临界段中的竞态条件

在上面的那个例子中的add方法的代码中包含了一个临界段。当多个线程执行这个临界段的时候,竞态条件就会发生了。

更正式的讲,两个线程的这种情形竞争着相同的资源,资源被访问的顺序是重要的,它被称为竞态条件。一个代码部分导致竞态条件就会被称之为临界段。

预防竞态条件

为了防止竞态条件的发生,你必须确保被执行的临界段作为一个原子指令被执行。那就意味着一旦一个单独的线程在执行它,其他的线程就不能执行它直到第一个线程已经离开了这个临界段。

竞态条件可以通过在临界段中使用线程同步的方式去避免。线程同步可以使用一个Java代码的同步锁去获取。线程同步也可以使用其他的同步概念去获取,像锁或者像java.util.concurrent.atomic.AtomicInteger的原子变量。

临界段的吞吐量

对于更小的临界段使得整个临界段的一个同步锁可能会工作。但是,对于更大的临界段,去把它分解成更小的临界段是更有意义的,使得允许多线程去执行每一个更小的临界段。整个就可能降低共享资源的竞争,以及增加整个临界段的吞吐量。

这里有一个非常简单的Java实例:

public class TwoSums {
    
    private int sum1 = 0;
    private int sum2 = 0;
    
    public void add(int val1, int val2){
        synchronized(this){
            this.sum1 += val1;   
            this.sum2 += val2;
        }
    }
}
Salin selepas log masuk


注意这个add方法是怎样往这两个sum变量中添加值得。为了预防竞态条件,在内部执行的求和有一个Java同步锁。伴随着这个实现,同时只能有一个线程可以执行这个求和。

然而,因为这两个sum变量是相互独立的,你可以把他们分离成两个分离的同步锁,像这样:

public class TwoSums {
    
    private int sum1 = 0;
    private int sum2 = 0;
    
    public void add(int val1, int val2){
        synchronized(this){
            this.sum1 += val1;   
        }
        synchronized(this){
            this.sum2 += val2;
        }
    }
}
Salin selepas log masuk


注意,两个线程可以同时执行这个add方法。一个线程获取到第一个同步锁,另外一个线程获取第二个同步锁。这种方式,线程之间将会等待的更少时间。

当然,这个例子是非常简单的。在真正的生活中,临界段分离的共享资源可能会更加复杂的,并且需要更多的执行顺序可能性的分析。


 以上就是Java 竞态条件和临界段的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Akar Kuasa Dua di Jawa Akar Kuasa Dua di Jawa Aug 30, 2024 pm 04:26 PM

Panduan untuk Square Root di Java. Di sini kita membincangkan cara Square Root berfungsi di Java dengan contoh dan pelaksanaan kodnya masing-masing.

Nombor Sempurna di Jawa Nombor Sempurna di Jawa Aug 30, 2024 pm 04:28 PM

Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Nombor Armstrong di Jawa Nombor Armstrong di Jawa Aug 30, 2024 pm 04:26 PM

Panduan untuk Nombor Armstrong di Jawa. Di sini kita membincangkan pengenalan kepada nombor Armstrong di java bersama-sama dengan beberapa kod.

Penjana Nombor Rawak di Jawa Penjana Nombor Rawak di Jawa Aug 30, 2024 pm 04:27 PM

Panduan untuk Penjana Nombor Rawak di Jawa. Di sini kita membincangkan Fungsi dalam Java dengan contoh dan dua Penjana berbeza dengan contoh lain.

Weka di Jawa Weka di Jawa Aug 30, 2024 pm 04:28 PM

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Nombor Smith di Jawa Nombor Smith di Jawa Aug 30, 2024 pm 04:28 PM

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Soalan Temuduga Java Spring Soalan Temuduga Java Spring Aug 30, 2024 pm 04:29 PM

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Cuti atau kembali dari Java 8 Stream Foreach? Cuti atau kembali dari Java 8 Stream Foreach? Feb 07, 2025 pm 12:09 PM

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

See all articles