线程安全性(二)

2018-06-02  本文已影响0人  墨平语凡

原子性 - 锁

原子性提供了互斥访问,同一时刻只能有一个线程对它进行操作。能保证同一时刻只有一个线程进行操作的,除了Atomic包之外还有。主要有

锁.jpg

原子性-synchronized

package io.haitaoc.concurrency.example.sync;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * synchronized示例
 */
public class SynchronizedExample1 {

    public void test1(int j) {
        // 修饰一个代码块, 作用于当前调用对象,不同对象间不影响
        synchronized (this) {             // 作用范围是 大括号括起来的部分, 作用对象是调用这部分代码的对象
            for (int i = 0; i < 10; i++) {
                System.out.println("test1 - " + i+" "+j);
            }
        }                               // 作用范围结束
    }

    // 修饰一个方法, 作用于当前调用对象,不同对象间不影响
    public synchronized void test2(int j) {      // 作用范围是整个方法, 作用调用此方法的对象
        for (int i = 0; i < 10; i++) {
            System.out.println("test2 - " + i+" "+j);
        }
    }

    public static void main(String[] args) {
        SynchronizedExample1 example1 = new SynchronizedExample1();
        SynchronizedExample1 example2 = new SynchronizedExample1();
        // 使用线程池, 相当于分别启动两个进程来执行test1()
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(()->{
            example1.test2(1);
        });
        executorService.execute(()->{
            example2.test2(2);
        });
    }
}

如果一个方法内部是一个完整的同步代码块,那么它和用synchronized修饰这个方法时等同的。注意:如果SynchronizedExample1是父类,其子类在调用test1()test2()时是不包含synchronized的,原因在于synchronized不属于方法声明的一部分,如果子类想要使用synchronized,需要自己显示地在方法上进行声明

package io.haitaoc.concurrency.example.sync;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * synchronized示例
 */
public class SynchronizedExample2 {

    public static void test1(int j) {
        // 修饰一个类
        synchronized (SynchronizedExample2.class) {             // 作用范围是 大括号括起来的部分, 作用对象是调用这部分代码的对象
            for (int i = 0; i < 10; i++) {
                System.out.println("test1 - " + i+" "+j);
            }
        }                               // 作用范围结束
    }

    // 修饰一个静态方法, 作用于所有对象, 同一时刻只有一个线程可以执行
    public static synchronized void test2(int j) {      // 作用范围是整个方法, 作用调用此方法的对象
        for (int i = 0; i < 10; i++) {
            System.out.println("test2 - " + i+" "+j);
        }
    }

    public static void main(String[] args) {
        SynchronizedExample2 example1 = new SynchronizedExample2();
        SynchronizedExample2 example2 = new SynchronizedExample2();
        // 使用线程池, 相当于分别启动两个进程来执行test1()
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(()->{
            example1.test1(1);
        });
        executorService.execute(()->{
            example2.test1(2);
        });
        executorService.shutdown();
    }
}

修饰类的整个代码块和修饰静态方法时的作用效果相同

compare.jpg
上一篇 下一篇

猜你喜欢

热点阅读