原子性提供了互斥访问:同一时刻只能有一个线程进行操作;

除了Atomic包类之外,还有锁可以实现此功能;

synchronized:  java关键字,依赖于jvm实现锁功能,被此关键字所修饰的,都是在同一时刻,只能有一个线程操作;

Lock: 由jdk提供的锁,Lock类,比如ReentranLock等..;

这次针对synchronized进行介绍:synchronized是一种同步锁,修饰对象有四种;

一,修饰代码块:大括号括起来的代码,作用于调用的对象,被修饰的代码称为同步语句块。

二,整个方法,作用于调用的对象,被修饰的方法称为同步方法。

三,整个静态方法,作用于所有对象。

四,修饰类,synchronized后面括号括起来的部分,作用于所有对象。

package com.example.concurrency.example.sync;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* @author xiaozhuang
* @date 2022年04月08日 14:47
*/
@Slf4j
public class SynchronizedExample1 { // 修饰代码块 作用于调用的对象
public void test1(){
synchronized (this){
for (int i = 0; i < 3; i++) {
log.info("修饰代码块:{}",i);
}
}
}
public static void main(String[] args) {
SynchronizedExample1 synchronizedExample1=new SynchronizedExample1();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(()->{
synchronizedExample1.test1();
});
executorService.execute(()->{
synchronizedExample1.test1();
});
executorService.shutdown();
}
}

先看看修饰代码块的例子,它是作用于调用的对象,这里我们根据对象 在线程池中调用了2次,test1方法,看一下输出

再改为两个对象调用时

发现它是交替按顺序输出的,它是作用于调用对象,所以不用对象调用之间是相互不影响的,在上面一个对象调用两次test1方法,则是需要一个执行完再执行另一个。

再看看修饰方法,也是作用于调用对象:

再看看两个对象调用时

可以看到输出是与上面的修饰代码块是一样;

可以得出一个结论:如果一个方法内部一整个都是同步代码块,那么它与用synchronized修饰的方法是等同的。

如果当前类是父类,当子类继承父类时,调用父类被synchronized修饰的方法时,是不会带上synchronized关键字的,需要自己手动加上去,synchronized不属于方法声明部分;

再看看修饰静态方法与修饰类的:

这里因为修饰类与修饰静态方法的作用于所有的对象,所以在这个类里,都是需要逐个执行完毕;

结论:如果一个方法里,一整个都是被synchronized所修饰的类包围的时候,那么它与被synchronized修饰的静态方法的作用是等同的。

通过上面对synchronized的了解,所以一个计数的问题也就迎刃而解了;

@Slf4j
public class ConcurrencyTest {
// 请求访问总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
// 计数的值
public static int count = 0;
public static void main(String[] args) throws InterruptedException {
// 线程池
ExecutorService executorService = Executors.newCachedThreadPool();
// 信号量 参数为 运行并发的数目
final Semaphore semaphore = new Semaphore(threadTotal);
// 递减计数器 参数为 请求数量 没执行成功一次会 减1
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
// 讲请求放入线程池中
executorService.execute(() -> {
try {
//判断信号量 判断当前线程是否允许被执行
semaphore.acquire();
add();
// 释放进程
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
// 没执行完一次 计算器-1
countDownLatch.countDown();
});
}
countDownLatch.await();
// 关闭线程池
executorService.shutdown();
log.info("count:{}", count);
}
private static void add() {
count++;
}
}

只需要在add()方法加上synchronized,就会变成线程安全了;

最后对比一下synchronized,Lock,Atomic三者的区别

synchronized:在执行到synchronized作用范围内的时候,它是不可中断的,必须等待代码执行完毕。适合竞争不激烈,可读性好,竞争激烈时,性能下降较快;

Lock:是可以中断的,只需要调用unLock就行,多样化同步,竞争激烈时能维持常态;

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

线程安全性-原子性之synchronized锁的更多相关文章

  1. Java并发编程入门与高并发面试(三):线程安全性-原子性-CAS(CAS的ABA问题)

    摘要:本文介绍线程的安全性,原子性,java.lang.Number包下的类与CAS操作,synchronized锁,和原子性操作各方法间的对比. 线程安全性 线程安全? 线程安全性? 原子性 Ato ...

  2. 4-3 线程安全性-原子性-synchronized

    原子性它提供了互斥访问,同一时刻只能有一个线程来对它进行操作.能保证同一时刻只有一个线程来对其进行操作的,除了Atomic包之外,还有锁.JDK提供锁主要分两种,synchronized是一个Java ...

  3. 并发与高并发(八)-线程安全性-原子性-synchronized

    前言 闲暇时刻,谈一下曾经在多线程教程中接触的同步锁synchronized,相当于复习一遍吧. 主要介绍 synchronized:依赖JVM Lock:依赖特殊的CPU指令,代码实现,Reetra ...

  4. 并发与高并发(七)-线程安全性-原子性-atomic

    一.线程安全性定义 定义:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程 ...

  5. 线程安全性-原子性之Atomic包

    先了解什么是线程安全性:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称为这个类是线程 ...

  6. java多线程中篇(二) —— 线程的创建和Synchronized锁关键字

    学习之前,先了解线程状态图 说明:线程共包括以下5种状态. 1. 新建状态(New)         : 线程对象被创建后,就进入了新建状态.例如,Thread thread = new Thread ...

  7. 4-2 线程安全性-原子性-atomic-2

    AtomicReference和AtomicLong.AtomicInteger很像,方法也基本上是一样的,然后我们通过引用Integer来做一个简单的例子. com.mmall.concurrenc ...

  8. Java线程安全性-原子性工具对比

    synchronized 不可中断锁,适合竞争不激烈的场景,可读性好,竞争激烈时性能下降很快 Lock 可中断锁,多样化同步,竞争激烈时能维持常态 Atomic 竞争激烈时能维持常态,比Lock性能还 ...

  9. 4-1 线程安全性-原子性-atomic-1

    我们发现在不做任何同步的情况下,我们计算的累加结果是错误的. com.mmall.concurrency.example.count.CountExample2 C:\Users\ZHONGZHENH ...

随机推荐

  1. Python程序的流程

    1 """ 2 python程序的流程 3 """ 4 # ------------- 分支结构---------------- 5 # i ...

  2. XXE漏洞——介绍及利用

    什么是xxe XML外部实体注入,简称XXE漏洞.XML文档结构包括XML声明,DTD文档类型定义,文档元素. XML示例 <?xml version="1.0"?>X ...

  3. JavaSE常用类之Object类

    1. hashCode方法 代码: package NeiBuLei; public class hashCode { public static void main(String[] args) { ...

  4. 聊聊UI自动化的PageObject设计模式

    当我们开发UI自动化测试用例时,需要引用页面中的元素(数据)才能够进行点击(动作)并显示出页面内容.如果我们开发的用例是直接对HTML元素进行操作,则这样的用例无法"应对"页面中U ...

  5. Codeforces Round #707 (Div. 2)A.英语漏洞 + C.Going Home C题收获不小

    A题英语漏洞 A题传送门: https://codeforces.com/contest/1501/problem/A 其实题目说的很明白, 只是我傻傻的会错了意, 话不多说, 开整. 前两行是说, ...

  6. 2021-01-25 cf #697 Div3 C题(超时,换思路减少复杂度)

    题目链接:https://codeforces.com/contest/1475/problem/C 题意要求:需组成的2对,男的序号不能重,女的序号不能重 比如这例 输入: 行1--测试个数 行1` ...

  7. 字符串/16进制/ASCII码的转换

    1 /// <字符串转16进制格式,不够自动前面补零> 2 /// 假设文本框里面填写的是:01 02 03 04 05 06 3 /// Str获取的是01 02 03 04 05 06 ...

  8. 如何向开源项目(Apache-InLong)提交代码

    目录 1 - 认领或提交 ISSUE 2 - clone 代码,本地编译安装 3 - 代码规范 4 - 提交代码 版权声明 Apache InLong(应龙)是一个一站式海量数据集成框架, 提供自动. ...

  9. kali 更换国内源

    打开source源 vim /etc/apt/sources.list 没有权限进行更改 获取root 权限 按 i 提示内容: E325: 注意 发现交换文件 "/var/tmp/sour ...

  10. [洛谷] P2241 统计方形(数据加强版)

    点击查看代码 #include<bits/stdc++.h> using namespace std; long long n, m, total, sum1, sum2; int mai ...