Javaの並行処理(JUC)---同期、ThreadLocalの、揮発性

スレッド間で共有

3つのキーワード:同期使用例、ThreadLocalの、揮発性の

ビルトイン1.Synchronizedロック

1)クラスロック:クラスは、各クラスのオブジェクト

    代码示例:
          类锁的方法和使用类锁的线程
          解析:在类锁的方法里用线程的休眠代表平常的业务工作(用static关键字修饰)
                     在类锁的线程只是做简单的输出和调用类锁的方法
//类锁的方法
    private static synchronized void synClass(){
        try {
            Thread.sleep(1000);
            System.out.println("synClass is going...");
            Thread.sleep(1000);
            System.out.println("synClass ended...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 //使用类锁的线程
    private static class SynClass extends Thread{
        @Override
        public void run() {
            System.out.println("TestClass is running");
            synClass();
        }
    }

2)オブジェクトのロック:各オブジェクト(新しいインスタンスアウト)

コード例:
オブジェクトのロックスレッド使用してオブジェクト・ロック法
分析:スレッド睡眠と出力文の通常の操作のロックオブジェクトを表すにおけるメソッド
オブジェクトのロックスレッドSynClzAndInsのメソッドを含む、これらのエンティティクラス、最初この新たなオブジェクトの例は、その後、オブジェクトロックの適切なメソッドを呼び出し

 //对象锁的方法
    private synchronized void instance(){
        try {
            Thread.sleep(3000);
            System.out.println("synInstance is going..."+this.toString());
            Thread.sleep(3000);
            System.out.println("synInstance ended..."+this.toString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 //使用对象锁的线程
    private static class InstanceSyn implements Runnable{
        private SynClzAndInst synClzAndInst;

        public InstanceSyn(SynClzAndInst synClzAndInst) {
            this.synClzAndInst = synClzAndInst;
        }

        @Override
        public void run() {
            System.out.println("TestInstance is running..."+synClzAndInst);
            synClzAndInst.instance();
        }
    }

最良のコードブロック(SynClzAndInstクラスは、クラス・ロックは、2つのスレッドとスレッド・ロックに使用されるオブジェクト、メソッドを使用して、クラスのロックとロックの2つのオブジェクトを使用する方法を使用含ま)

package 线程间的共享;

/**
 * @author lenovo
 */
public class SynClzAndInst {

    //使用类锁的线程
    private static class SynClass extends Thread{
        @Override
        public void run() {
            System.out.println("TestClass is running");
            synClass();
        }
    }
    //使用对象锁的线程
    private static class InstanceSyn implements Runnable{
        private SynClzAndInst synClzAndInst;

        public InstanceSyn(SynClzAndInst synClzAndInst) {
            this.synClzAndInst = synClzAndInst;
        }

        @Override
        public void run() {
            System.out.println("TestInstance is running..."+synClzAndInst);
            synClzAndInst.instance();
        }
    }
    //使用对象锁的线程
    private static class Instance2Syn implements Runnable{
        private SynClzAndInst synClzAndInst;

        public Instance2Syn(SynClzAndInst synClzAndInst) {
            this.synClzAndInst = synClzAndInst;
        }

        @Override
        public void run() {
            System.out.println("TestInstance2 is running..."+synClzAndInst);
            synClzAndInst.instance2();
        }
    }
    //对象锁的方法
    private synchronized void instance(){
        try {
            Thread.sleep(3000);
            System.out.println("synInstance is going..."+this.toString());
            Thread.sleep(3000);
            System.out.println("synInstance ended..."+this.toString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //对象锁的方法
    private synchronized void instance2(){
        try {
            Thread.sleep(3000);
            System.out.println("synInstance2 is going..."+this.toString());
            Thread.sleep(3000);
            System.out.println("synInstance2 ended..."+this.toString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //类锁的方法
    private static synchronized void synClass(){
        try {
            Thread.sleep(1000);
            System.out.println("synClass is going...");
            Thread.sleep(1000);
            System.out.println("synClass ended...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        SynClzAndInst synClzAndInst=new SynClzAndInst();
        Thread t1=new Thread(new InstanceSyn(synClzAndInst));

        SynClzAndInst synClzAndInst2=new SynClzAndInst();
        Thread t2=new Thread(new Instance2Syn(synClzAndInst2));

//        SynClass t2=new SynClass();


        t1.start();
        t2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

結果を実行します。
ここに画像を挿入説明
最終的には、言いました:

(彼らは別のオブジェクトであるため、ロック)、それはクラスのロックまたはロックオブジェクトを使用することとの間にあるかどうか、スレッドが共有されている、彼らは同時に実行することができます。実際の開発では、我々は彼らだけがリソースの競合を生産する2つの異なるオブジェクトを、ロックする新しいロックを持っています

2.ThreadLocal(スレッド変数)

    1)它的底层实现是Map,主要应用在线程池的连接里面
    2)三个常用的方法:  protected T initialValue()           //初始化值
                     ThreadLocal.get()                    //获取值
                     ThreadLocal.set()                    //设置值				                                          

使用コードThreadLocalのインスタンス:
ビジネス・ニーズ:オープン複数のスレッドは、作業が変化し、ライトバックアウト初期スレッドの変数の後に行われるスレッドは、変数のこれらのスレッドが互いに影響を観察します。

そしてThreadLocalの初期コーティングの新しいクラスが
あってはinitialValue()は、コーティングの初期値であり、

static ThreadLocal<Integer> threadLocal= new ThreadLocal<Integer>(){

        @Override
        protected Integer initialValue() {
            return 1;
        }
    };

オープンスレッドの新しいスレッドの配列を作成します。

/**
     * 运行3个线程
     */
    public static void StartThreadArray(){
        Thread[] runs=new Thread[3];
        for(int i=0;i<runs.length;i++){
            runs[i]=new Thread(new TestThread(i));
        }
        for (int i=0;i<runs.length;i++){
            runs[i].start();
        }
    }

具体的な運用スレッド:初期にThreadLocalは、スレッドごとにとられており、各スレッドは、ID番号を追加し、書き込みます。結果の値を考慮したスレッドの結果がお互いに影響を与えます。


    /**
     * 类说明:测试线程,线程的工作是将ThreadLocal的变量变化,并写回,
     * 看线程之间是否相互影响
     */
    public static class TestThread implements Runnable{
        int id;
        public TestThread(int id){
            this.id=id;
        }
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+" start");
            Integer s=threadLocal.get(); //获得变量的值
            s=s+id;
            threadLocal.set(s);
            System.out.println(Thread.currentThread().getName()+":"+
                    threadLocal.get());
        }
    }

完全なコード

package 线程间的共享;

/**
 * @author lenovo
 * 类说明:使用类ThreadLocal
 */
public class UseThreadLocal {
    static ThreadLocal<Integer> threadLocal= new ThreadLocal<Integer>(){

        @Override
        protected Integer initialValue() {
            return 1;
        }
    };
    /**
     * 运行3个线程
     */
    public static void StartThreadArray(){
        Thread[] runs=new Thread[3];
        for(int i=0;i<runs.length;i++){
            runs[i]=new Thread(new TestThread(i));
        }
        for (int i=0;i<runs.length;i++){
            runs[i].start();
        }
    }

    /**
     * 类说明:测试线程,线程的工作是将ThreadLocal的变量变化,并写回,
     * 看线程之间是否相互影响
     */
    public static class TestThread implements Runnable{
        int id;
        public TestThread(int id){
            this.id=id;
        }
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+" start");
            Integer s=threadLocal.get(); //获得变量的值
            s=s+id;
            threadLocal.set(s);
            System.out.println(Thread.currentThread().getName()+":"+
                    threadLocal.get());
        }
    }

    public static void main(String[] args) {
        StartThreadArray();
    }
}

実行結果は、
ここに画像を挿入説明
分析結果:ThreadLocalの初期値は1、スレッド0は、スレッドある 1は、識別番号スレッド2は、0,1,2であった。
結果から、ThradLocalオブジェクトの唯一のインスタンスが。しかし、スレッドが変数ごとに個別のスレッドとして見られている、実行されている、それがスレッド間には影響しません。したがって、スレッド0は、スレッド1、スレッド2は、そのほかのIDがそれぞれ結果値1,2,3を行い、初期値は1で取得します。

3.キーワードの揮発性:

1)最も軽量な同期メカニズムが、スレッドセーフではありません、保証アトミックない
2)シナリオ:書き込み専用スレッドを1つ、複数のスレッドを読んで(それは()アトミック操作を保証することはできません、変数の視認性を確保することができますアトミック:いずれかの実行の完了とともに、または行いません)

分析:可視性変数:スレッド内の変数の可視性を確保するために、すべてのスレッドがいることを確実にするために、揮発性の変数は、直ちに作業メモリの変更後の動作の後、メインメモリから読み出され、メインメモリにライトバックされなければならないアクセス可視他のスレッドが
アトミック操作を保証することはできません:「アトミック操作(原子操作)同期要求されない」、マルチスレッドプログラミング一般的です。いわゆるアトミック操作は中断されたスレッドのスケジューリングメカニズムが作動できない意味し、この操作を開始したら、それが完了するまで実行されます。(矛盾スケジューリングメカニズムに起因する可能性が実行されている複数のスレッドが、刻々と変化する結果をもたらすように)

サンプルコード

package 线程间的共享;

/**
 * @author lenovo
 * 类说明:volatile无法提供操作的原子性
 */
public class VolatileUnsafe {

    private static  class VolatileVar implements Runnable{
        private volatile int a=0;

        @Override
        public void run() {
            String threadName=Thread.currentThread().getName();
            a=a+1;
            System.out.println(threadName+":======"+a);
            try {
                Thread.sleep(100);
                a=a+1;
                System.out.println(threadName+":======"+a);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        VolatileVar v=new VolatileVar();

        Thread t1=new Thread(v);
        Thread t2=new Thread(v);
        Thread t3=new Thread(v);
        Thread t4=new Thread(v);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

業績
ここに画像を挿入説明
ここに画像を挿入説明
二つのグラフ上では、私たちの最も直感的な感覚の予測不可能性によって生成されたコードの同じ部分を実行している別の結果である多様性と結果の結果です。もちろん、これは我々がコードを書くとき、ほとんどは見たくないです。(我々はそれが変数値の2個の原子が0スレッドすべきであることを保証できる場合、設計手順が、各蓄積動作をスレッドする変更マインドは1、2であり;糸ターンの1つの二つの可変値が3,4であります...ように。上記の結果は同じで、明らかにできないと私たちは期待して、揮発性の変数は保証アトミック操作することができないため、これは、スレッドが0の実行、それが可変の動作時間を持っているとき、他のスレッドが取得する機会を持っています変数は、スレッド0が第二の完全な値に応じて変化に期待できない原因となる、というように、各スレッドは、オペレーティング・システムによって、可変スケジューリングの決定の可能性を得るために、結果も)価値観の多様化につながります

公開された19元の記事 ウォンの賞賛2 ビュー421

おすすめ

転載: blog.csdn.net/TheWindOfSon/article/details/103329549