マルチスレッドへの構想から基本原則へ

1. スレッドとプロセスとの間の差

プロセスとスレッド:プログラムは、伝統的なコンピュータのオペレーティングシステムに対して個別に実行することができ、プロセスは、基本単位の資源配分およびスケジューリングですが、それぞれの時間はスイッチングの異なるプロセスに、オペレーティング・システムやソフトウェアがありますデータ復旧と 新たなデータの再配分、その改善を行うために、このような状況のための伝統的なコンピュータのオペレーティングシステム、その瞬間、コンピュータのオペレーティングシステムは、リソース割り当ての基本単位としてちょうどプロセスであり、実行およびスケジューリングのスレッドとして基本ユニット、プログラム・リソースの各スレッドのスケジューリングおよび実行が非常に小さいメモリフットプリント、低オーバーヘッド、それによって増加しているため、CPUの処理能力を

要約すると:

            コードセグメントのセクションを別々に行ってもよい:スレッドを

       プロセス:リソースを対応する実行のすべてのスレッドの瞬間、すべてのスレッドおよびプロセスの動作状態を示すフラグは、(すべてのリソースおよび実行中のスレッドの実行中のすべてのスレッドを含有し、その走行状態フラグをマーク)

2.  実行、同時並列区別のため

実行順序:教師家庭教師、学生、より多くの宿題、最初の学生の前に個別指導、問題に問題を説明するために、学生をランク付けが完了した後とは、消化終わっ二学生のカウンセリングを説明します

同時実行:最初の学生が最初の質問を消化する際の問題点を説明した後、最初の生徒の個別指導の前に学生を家庭教師の先生よりはカウンセリングに2番目の学生は、このように多くの時間を節約しながら、教師はできない、完成されましたカウンセリング停止( CPUが実行するI / O操作)

パラレル:より多くの教師が一対一で一人の生徒を家庭教師

3 スレッドのいくつかの状態

 

 

  新しい状態:新しいスレッドを作成するための新しいキーワード

  実行実行状態

  ①あなたが順番に実行可能startメソッドを実行した後、スレッドの新しい状態がすぐに実行されないと、CPU時間がこのスレッドの後部に割り当てられたCPUの待機時間、状態の実行状態にスレッドを割り当てることができます

  ②現在のスレッド実行睡眠()メソッドは、()メソッドまたはユーザ入力、ブロックされた状態にスレッドを待っている時間に参加し、スリープ()、ユーザー入力の待ち()メソッドが完了または終了したときにスレッドが実行可能状態になります

  ③待機中のプールにスレッドの待機()メソッドの後に、現在のスレッドに、実行の他のスレッドがランダムウェイクアップスレッドロックプールにスタンバイプールからなります()メソッドを、通知した場合、別のスレッドがのnotifyAll()メソッドを呼び出した場合は、待機中に置きますすべてのスレッド内のプールは、プールにロックされています

  ④オブジェクトのロックを獲得するスレッドの内部プールをロックし、スレッドが実行を開始します

 死のステータス:

  ①スレッドが自然死を終了します

  ②が表示され、例外をスローし、抑圧することを余儀なく

 

4 オペレーティング・システムまたはソフトウェアのスレッドが実行中のJVM の動作を

大学はすべてが真実を知っている必要がありますコンピュータの構成原理を研究し、 CPUは読んで、ハードウェアのメモリよりもはるかに高速で実行され、ハードウェアの速度を生成するように、書き込み速度の問題で実行されているリミットコンピュータを、それはメモリとの間の速度で、CPU間のキャッシュキャッシュはまた、データがメモリに読み出されていない場合は、キャッシュを見つけるに移動し、対応するメモリになるときCPUがキャッシュアドレスに従ってデータを検索したときに一時的にデータを格納するメモリを担当している、されて入ってきましたキャッシュバッファへのデータは、次回を読み取るためのキャッシュメモリなどポーターのCPUとの間で、図以下。

 

 

 

 

 

現在広く普及しマルチコアコンピュータの CPU、私たちは今、チャートを見て

 

                               

      マルチコア前側CPUマルチコアCPU

 

                    

 

現在のコンピュータは、一般に、マルチコアであるため、 CPU、本当の意味での(複数のスレッドが同時に実行)並行して達成することができるだけでなく、より多くの同時スレッドが(同一の複数のスレッドを実行するために同じ時間)を達成するが、複数のスレッドを達成する方法データベースの操作はありますか?これは、前述したように、JVMを必要とします

 

 

 

VMスタック:情報を記憶するためのローカル変数テーブル、オペランドスタック、動的リンク、方法輸出。

本地方法:用于存储进程调用的native方法

 

知道上面这些和之前我们在第一部分提到的线程和进程的区别就好说啦;因为一个进程就相当于一个软件,当一个软件启动的时候jvm会作出什么工作呢?

① 当进程启动时操作系统会将此进程运行时需要的所有相关数据都加载到jvm对应区域,把图片,视频,等所有的或者部分(视当前运存大小而定)静态资源加载到方法区内,此时进程启动完毕,等待要执行的线程

② 单线程时:线程开始执行,CPU根据虚拟机栈里面的存储局部变量表去堆里面找寻对应的数据,若找不到则去内存中寻找,然后线程结束的时候会将此单个线程工作区里面的数据写回到内存。

③ 多线程时(不加锁):当出现多线程的时候,jvm会把堆根据线程一一对应进行分解变成一个个的线程工作区,每一个工作区内的数据都是一样的,相当于将内存的对应数据映射到工作区。当等待池中的某个线程获取到CPU时间后开始执行;若其对应的线程工作区里面的数据发生改变,则不会导致对应内存的数据发生变化,如果此时其它在等待池的线程获取到CPU时间的时候也对自己线程工作区的此数据修改则产生数据不一致,这是产生数据不一致的根本原因。

④ 多线程时(加锁):当jvm在加载 .class 文件时,当遇到synchronized关键字,则会在被锁代码前面加monitorenter关键字,在末端加monitorexit关键字,等待池中的某个线程获取到对象监听器(锁)的时候线程工作区从内存读取数据然后此线程进入锁池,锁池中的线程获取到cpu时间则对自己线程工作区的数据进行操作;每遇到一次monitorenter时对象的锁计数器加一,若遇到monitorexit时锁计数器减一,当计数器为0的时候释放锁;然后将对处理后的对象数据写回到内存中从而实现线程之间数据的通信。如下图

 

 

 

 

综上所述:加锁是为了线程安全,本质上是为了在每次线程执行完毕之后将工作区的的对象的数据写回到内存;每次线程执行之前将工作区对应的数据更新从而保持数据的一致性和实现线程之间的通信,然而实现这种效果需要满足多线程的原子性,可见性和有序性

5. 满足线程安全的三个属性

原子性:各个线程之间进行数据的互斥访问,同时刻只能有一个线程对数据进行操作

 

可见性:一个线程对数据修改后可以被其它线程看到(线程之间实现通信)

 

有序性:Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。而有序性是指程序的代码执行顺序和语句的顺序是一致的。

6. 实现三个属性的方法

原子性:保证原子性的方法有atomicsynchronized,前者应用不是太多,这里主要介绍后者;

    synchronized修饰的对象有四种(原理在上文已经提到)

1)修饰代码块,作用于调用的对象;

2)修饰方法,作用于调用的对象;

3)修饰静态方法,作用于所有对象;

4)修饰类,作用于所有对象。

可见性volatile,声明变量的时候前面添加volatile关键字,每次多线程对工作区内的此变量进行操作后都强制将其写回内存,每次要操作此变量时强制更新来实现多线程的工作区数据和内存对应数据保持一致,进而间接实现多个线程之间的数据通信。

 

有序性可以通过volatile、synchronized、lock保证有序性。

另外,JMM具有先天的有序性,即不需要通过任何手段就可以得到保证的有序性。这称为happens-before原则。

 

如果两个操作的执行次序无法从happens-before原则推导出来,那么它们就不能保证它们的有序性。虚拟机可以随意地对它们进行重排序。

 

happens-before原则:

 

1.程序次序规则:在一个单独的线程中,按照程序代码书写的顺序执行。

 

2.锁定规则:一个unlock操作happen—before后面对同一个锁的lock操作。

 

3.volatile变量规则:对一个volatile变量的写操作happen—before后面对该变量的读操作。

 

4.线程启动规则:Thread对象的start()方法happen—before此线程的每一个动作。

 

5.线程终止规则:线程的所有操作都happen—before对此线程的终止检测,可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测到线程已经终止执行。

 

6.线程中断规则:对线程interrupt()方法的调用happen—before发生于被中断线程的代码检测到中断时事件的发生。

 

7.对象终结规则:一个对象的初始化完成(构造函数执行结束)happen—before它的finalize()方法的开始。

 

8.传递性:如果操作A happen—before操作B,操作B happen—before操作C,那么可以得出A happen—before操作C。

 

 

 

 

 

 

有部分借鉴的大佬的,有些自己总结的,欢迎指出错误

おすすめ

転載: www.cnblogs.com/yzml/p/11668267.html