Synchronized

admin
2022-04-21 / 0 评论 / 169 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2022年04月24日,已超过943天没有更新,若内容或图片失效,请留言反馈。

Atomic原子性提供了互斥访问。同一时刻只能由一个线程来操作。除了Atomic原子性,还有锁。

jdk提供的锁主要分2类

1、Synchronized:一种依赖JVM去实现锁的关键字,Synchronized,在这个对象作用的范围内,都是同一时刻,只能有一个线程去操作。注意是,作用对象的作用范围内。

2、另一种jdk代码层面的锁,jdk里面提供了一个Lock的接口,主要是依赖特殊的CPU指令,实现类中比较有代表性的是ReentrantLock。

Synchronized

一种同步锁,修改的对象主要有4种:

  1. 修饰代码块:大括号括起来的代码,也就是同步语句块,它的作用范围是大括号括起来的代码,作用对象是调用代码块的对象
  2. 修饰方法:被称为同步方法,作用范围为整个方法,作用对象是也是调用该方法的对象
  3. 修饰静态方法:作用范围整个静态方法,作用对象是这个类的所有对象
  4. 修饰类:修饰内容是后面Synchronized括号括起来的部分,作用对象也是这个类的所有对象

代码说明:

一、启用不同进程,同一对象调用,调用同一方法。

package com.yanxizhu.demo.concurrency.sync;

import lombok.extern.slf4j.Slf4j;

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

/**
 * @description: Synchronized修饰代码块、修改方法,作用对象为调用对象
 * 这里测试,同一对象,启动不同进程,调同一方法
 * @author: <a href="mailto:batis@foxmail.com">清风</a>
 * @date: 2022/4/20 22:44
 * @version: 1.0
 */
@Slf4j
public class DemoSynchronizedOne {

    /**
     * 修饰代码块,大括号被称为 同步代码块,
     * 作用范围:代码块内
     * 作用对象:调用代码块的对象
     */
    public void test1() {
        synchronized (this) {
            for (int i = 0; i < 10 ;i ++){
                log.info("test1 ...i={}",i);
            }
        }
    }

    /**
     * 修饰方法,该方法被称为同步方
     * 作为范围:整个test2方法
     * 作用对象:调用代码块的对象
     */
    public synchronized void test2() {
        for (int i = 0; i < 10 ;i ++){
            log.info("test2 ...i={}",i);
        }
    }

    public static void main(String[] args) {
        DemoSynchronizedOne demoSynchronized = new DemoSynchronizedOne();
        //线程池
        ExecutorService executorService = Executors.newCachedThreadPool();

        /**
         * 说明: 为什么执行2次
         * 如果不用线程池,下面2次调用都是同一线程,不能验证。
         * 使用线程池,相当于用了2各进程去执行test1,不用等一个进程执行完,在执行第二个线程,
         * 这样才能看到同一个对象的不同进程的执行情况。
         */
        //-----------------------------------测试同一对象的方法test1-------------------------------------------
//        测试1:
       executorService.execute(() -> {
           demoSynchronized.test1();
        });
        executorService.execute(() -> {
            demoSynchronized.test1();
        });

/*        输出结果:
23:33:52.670 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=0
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=1
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=2
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=3
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=4
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=5
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=6
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=7
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=8
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=9
23:33:52.674 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=0
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=1
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=2
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=3
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=4
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=5
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=6
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=7
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=8
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=9*/

        //-----------------------------------测试同一对象的方法test2-------------------------------------------
//        测试2:
        executorService.execute(() -> {
            demoSynchronized.test2();
        });
        executorService.execute(() -> {
            demoSynchronized.test2();
        });

/*        输出结果:
23:33:24.291 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=0
23:33:24.295 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=1
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=2
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=3
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=4
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=5
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=6
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=7
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=8
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=9
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=0
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=1
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=2
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=3
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=4
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=5
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=6
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=7
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=8
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=9*/

        executorService.shutdown();
    }
}

二、启动不同进程,不同对象,调用同一方法

package com.yanxizhu.demo.concurrency.sync;

import lombok.extern.slf4j.Slf4j;

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

/**
 *
 * @description: Synchronized修饰代码块、修改方法,作用对象为调用对象
 * 这里测试,不同对象,启动不同进程,调同一方法
 * @author: <a href="mailto:batis@foxmail.com">清风</a>
 * @date: 2022/4/20 22:44
 * @version: 1.0
 */
@Slf4j
public class DemoSynchronizedTwo {

    /**
     * 修饰代码块,大括号被称为 同步代码块,
     * 作用范围:代码块内
     * 作用对象:调用代码块的对象
     */
    public void test1(int j) {
        synchronized (this) {
            for (int i = 0; i < 10 ;i ++){
                log.info("test1 ...i={},j={}",i,j);
            }
        }
    }

    /**
     * 修饰方法,该方法被称为同步方
     * 作为范围:整个test2方法
     * 作用对象:调用代码块的对象
     */
    public synchronized void test2(int j) {
        for (int i = 0; i < 10 ;i ++){
            log.info("test2 ...i={},j={}",i,j);
        }
    }

    public static void main(String[] args) {
        DemoSynchronizedTwo demoSynchronizedTwo = new DemoSynchronizedTwo();
        DemoSynchronizedTwo demoSynchronizedTwo2 = new DemoSynchronizedTwo();
        //线程池
        ExecutorService executorService = Executors.newCachedThreadPool();

        //-----------------------------------测试同一对象的方法test1,作用代码块-------------------------------------------
//        executorService.execute(()->{
//            demoSynchronizedTwo.test1(1);
//            demoSynchronizedTwo2.test1(2);
//        });
/*        输出结果:
        23:28:57.763 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=0,j=1
        23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=1,j=1
        23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=2,j=1
        23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=3,j=1
        23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=4,j=1
        23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=5,j=1
        23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=6,j=1
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=7,j=1
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=8,j=1
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=9,j=1
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=0,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=1,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=2,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=3,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=4,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=5,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=6,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=7,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=8,j=2
        23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=9,j=2*/

        /*
        * 结论:说明作用于同步代码,不同对象的调用是相互不影响的
        * */


        //-----------------------------------测试同一对象的方法test2,作用方法-------------------------------------------
        executorService.execute(()->{
            demoSynchronizedTwo.test2(1);
            demoSynchronizedTwo2.test2(2);
        });

/*        输出结果:
        23:34:56.130 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=0,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=1,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=2,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=3,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=4,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=5,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=6,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=7,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=8,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=9,j=1
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=0,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=1,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=2,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=3,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=4,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=5,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=6,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=7,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=8,j=2
        23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=9,j=2*/

        /*
         * 结论:说明作用于方法,不同对象的调用是相互不影响的
         * */
        executorService.shutdown();
    }
}

1和2对别结论:修饰带块和修改方法对别结论

1、当一个方法内都是用同步代码块修饰的,和修饰方法是一样的。

例如上面的:

 public void test1(int j) {
        synchronized (this) {
            for (int i = 0; i < 10 ;i ++){
                log.info("test1 ...i={},j={}",i,j);
            }
        }
    }
等同与下面的修饰方法:
    public synchronized void test2(int j) {
        for (int i = 0; i < 10 ;i ++){
            log.info("test2 ...i={},j={}",i,j);
        }
    }

2、修饰静态代码块和修饰方法,作用对象都是调用对象。

3、如果某个子类继承了上面的类,子类种test2方法是不带synchronized关键字的,因为synchronized不输入方法申明的一部分,如果子类想使用,则需要显示自己加synchronized。


三、不同对象调用同一方法,synchronized修改类和方法:

package com.yanxizhu.demo.concurrency.sync;

import lombok.extern.slf4j.Slf4j;

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

/**
 *
 * @description: Synchronized修饰静态方法、类
 * @author: <a href="mailto:batis@foxmail.com">清风</a>
 * @date: 2022/4/20 22:44
 * @version: 1.0
 */
@Slf4j
public class DemoSynchronizedThredd {

    //修饰类
    public static void test1(int j) {
        synchronized (DemoSynchronizedThredd.class) {
            for (int i = 0; i < 10 ;i ++){
                log.info("test1 ...i={},j={}",i,j);
            }
        }
    }

    //修饰静态方法
    public static synchronized void test2(int j) {
        for (int i = 0; i < 10 ;i ++){
            log.info("test2 ...i={},j={}",i,j);
        }
    }

    public static void main(String[] args) {
        DemoSynchronizedThredd demoSynchronizedTwo = new DemoSynchronizedThredd();
        DemoSynchronizedThredd demoSynchronizedTwo2 = new DemoSynchronizedThredd();
        //线程池
        ExecutorService executorService = Executors.newCachedThreadPool();

        //-----------------------------------测试同一对象的方法test1,作用代码块-------------------------------------------
        executorService.execute(()->{
            demoSynchronizedTwo.test1(1);
            demoSynchronizedTwo2.test1(2);
        });
/*        输出结果:
23:49:32.176 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=0,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=1,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=2,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=3,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=4,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=5,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=6,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=7,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=8,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=9,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=0,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=1,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=2,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=3,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=4,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=5,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=6,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=7,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=8,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=9,j=2*/



        //-----------------------------------测试同一对象的方法test2,作用方法-------------------------------------------
/*        executorService.execute(()->{
            demoSynchronizedTwo.test2(1);
            demoSynchronizedTwo2.test2(2);
        });*/

/*        输出结果:
23:47:13.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=0,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=1,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=2,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=3,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=4,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=5,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=6,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=7,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=8,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=9,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=0,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=1,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=2,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=3,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=4,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=5,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=6,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=7,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=8,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=9,j=2*/

        executorService.shutdown();
        /**
         * 说明:修饰类和修改静态方法是一样的
         */
    }
}

结论:修改类和静态方法,作用效果是一样的。


测试:

之前计数通过Atomic原子保证互斥性,现在通过Synchronized保证互斥性。

package com.yanxizhu.demo.concurrency.sync;

import com.yanxizhu.demo.concurrency.annotation.ThreadSafety;
import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety;
import lombok.extern.slf4j.Slf4j;

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

/**
 * @description: 线程不安全,不正确的
 * @author: <a href="mailto:batis@foxmail.com">清风</a>
 * @date: 2022/4/19 19:28
 * @version: 1.0
 */
@ThreadSafety
@Slf4j
public class DemoSemaphoreAndCountDownLatch {

    //用户数量
    private static final int clientsTotal = 5000;
    //并发数量
    private static final int concurrencyTotal = 200;
    //累加总和
    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        //信号量
        final Semaphore semaphore = new Semaphore(concurrencyTotal);
        //闭锁
        final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal);

        for (int i = 0; i < clientsTotal; i++) {
            executorService.execute(()->{
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (InterruptedException e) {
                    log.error("出现错误:【{}】", e.getMessage());
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.info("累加结果为count=【{}】",count);
    }

    /**
     * 累加
     */
    private synchronized static void add(){
        count++;
    }

}

原子性对比

synchronized:不可中断锁,适合竞争不激烈,可读性好

Lock:可中断锁,多样化同步,竞争激烈时能维持常态

Atomic:竞争激烈时能维持常态,比Lock性能好;只能同步一个值

1

评论 (0)

取消