前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >synchronized(1)

synchronized(1)

作者头像
黑洞代码
发布2021-01-14 15:48:10
3630
发布2021-01-14 15:48:10
举报

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();

    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 落叶飞翔的蜗牛 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档