synchronized(1)

2021-01-14 15:48:10 浏览数 (1)

synchronized(1)

概述


1.synchronized的作用

2.synchronized使用方式

3.synchronized导致的死锁

第1节 synchronized的作用


在并发编程中存在线程安全问题,主要原因有:

1.存在共享数据

2.多线程共同操作共享数据。

关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,实现线程安全。

第2节 synchronized使用方式


synchronized可以使用在代码块和方法中,根据使用的位置不同,可以有这些使用场景:

synchronized可以用在方法上也可以使用在代码块中,

使用在实例方法锁的是实例对象。

使用在静态方法锁的是类对象。

使用在代码块中也可以分为三种,具体的可以看上面的表格。

这里的需要注意的是:

如果锁的是类对象的话,尽管new多个实例对象,

但他们仍然是属于同一个类依然会被锁住,即线程之间保证同步关系。

代码语言:javascript复制
/**
 * @Author: 超神的蜗牛
 * @Date: 2019-07-22 19:53
 * @Description: 多个线程访问同一个对象的同一个方法
 */
public class SynchronizedTest01 implements Runnable {
    /**
     * 共享资源
     */
    static int counter = 0;

    /**
     * synchronized 修饰实例方法
     */
    public synchronized void increase() {
        for (int j = 0; j < 10; j  ) {
            System.out.println(Thread.currentThread().getName()   "执行累加操作。。。");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            counter  ;
        }
    }

    @Override
    public void run() {
        increase();
    }

    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest01 test = new SynchronizedTest01();
        Thread t1 = new Thread(test, "线程1");
        Thread t2 = new Thread(test, "线程2");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(counter);
    }
}

执行结果:

线程1执行累加操作。。。
线程1执行累加操作。。。
线程1执行累加操作。。。
线程1执行累加操作。。。
线程1执行累加操作。。。
线程1执行累加操作。。。
线程1执行累加操作。。。
线程1执行累加操作。。。
线程1执行累加操作。。。
线程1执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
线程2执行累加操作。。。
20
代码语言:javascript复制
/**
 * @Author: 超神的蜗牛
 * @Date: 2019-07-22 19:59
 * @Description: 一个线程获取了该对象的锁之后,其他线程来访问其他synchronized实例方法现象
 */
public class SynchronizedTest02 {
    /**
     * 同步方法1
     */
    public synchronized void method1() {
        System.out.println("Method 1 started:t"   TimeUtils.currentTime());
        try {
            System.out.println("Method 1 executed:t"   TimeUtils.currentTime());
            // sleep方法不会释放监视锁
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 1 ended:t"   TimeUtils.currentTime());
    }

    /**
     * 同步方法2
     */
    public synchronized void method2() {
        System.out.println("Method 2 started:t"   TimeUtils.currentTime());
        try {
            System.out.println("Method 2 executed:t"   TimeUtils.currentTime());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 2 ended:t"   TimeUtils.currentTime());
    }


    public static void main(String[] args) {
        final SynchronizedTest02 test = new SynchronizedTest02();

        new Thread(() -> test.method1()).start();

        new Thread(() -> test.method2()).start();
    }
}

执行结果:

Method 1 started:2019-07-24 23:57:21
Method 1 executed:2019-07-24 23:57:21
Method 1 ended:2019-07-24 23:57:31
Method 2 started:2019-07-24 23:57:31
Method 2 executed:2019-07-24 23:57:31
Method 2 ended:2019-07-24 23:57:32
代码语言:javascript复制
/**
 * @Author: 超神的蜗牛
 * @Date: 2019-07-22 20:19
 * @Description: 一个线程获取了该对象的锁之后,其他线程来访问其他非synchronized实例方法现象
 */
public class SynchronizedTest03 {
    /**
     * 同步方法1
     */
    public synchronized void method1() {
        System.out.println("Method 1 started:t"   TimeUtils.currentTime());
        try {
            System.out.println("Method 1 execute:t"   TimeUtils.currentTime());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 1 ended:t"   TimeUtils.currentTime());
    }
    /**
     * 同步方法2
     */
    public void method2() {
        System.out.println("Method 2 started:t"   TimeUtils.currentTime());
        try {
            System.out.println("Method 2 execute:t"   TimeUtils.currentTime());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 2 ended:t"   TimeUtils.currentTime());
    }


    public static void main(String[] args) {
        final SynchronizedTest03 test = new SynchronizedTest03();

        new Thread(() -> test.method1()).start();

        new Thread(() -> test.method2()).start();
    }
}

执行结果:

第3节 synchronized导致的死锁


代码语言:javascript复制
/**
 * @Author: 超神的蜗牛
 * @Date: 2019-07-23 22:36
 * @Description: synchronized造成的死锁
 *
 * 任何一个Java对象都可以充当一把锁
 *
 * 分别定义"A" 和 "B"两把锁
 *
 * 启动两个线程t1 和 t2
 *
 * 不管t1或者t2谁先获取到CPU使用权都会死锁(start()方法使线程进入可运行状态——具体参考之前的视频)
 *
 * 1.假设t1优先获取CPU使用权,进入运行态。线程t1获取到A锁后休眠2s(休眠不会释放锁),然后尝试获取B锁
 *   随后t2获取CPU使用权,进入运行态。线程t2获取到B锁后休眠2s(休眠不会释放锁),然后尝试获取A锁
 *   这时候t1休眠结束,t1尝试获取B锁,等待t2释放B锁
 *   这时候t2休眠结束,t2尝试获取A锁,等待t1释放A锁
 *   t1和t2相互等待对方释放锁,此时造成死锁。
 *
 * 2.线程t2优先获取到CPU使用的情况与1类似。
 *
 */
public class DeadLock {

    /** A锁 */
    private static String A = "A";

    /** B锁 */
    private static String B = "B";

    public static void main(String[] args) {
        new DeadLock().deadLock();
    }

    public void deadLock() {

        /**
         * 先获取A锁再获取B锁
         */
        Thread t1 = new Thread(() -> {
            synchronized (A) {
                try {
                    // 获取A锁后休眠2s
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (B) {
                    // 获取B锁
                    System.out.println("thread1...");
                }
            }
        });

        /**
         * 先获取B锁再获取A锁
         */
        Thread t2 = new Thread(() -> {
            synchronized (B) {
                try {
                    // 获取B锁后休眠2s
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (A) {
                    System.out.println("thread2...");
                }
            }
        });

        t1.start();
        t2.start();

    }

}

0 人点赞