synchronized各种使用场景

这篇具有很好参考价值的文章主要介绍了synchronized各种使用场景。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

多线程存在的问题

案例

开启10个线程,每个线程中循环100次对result变量进行++自增,主线程等待10s后输出result值结果

public class SynchronizedCase {
    private static Integer result = 0;
    
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 100; j++) {
                    result++;
                }
            }).start();
        }
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("执行结果 result : " + result);
    }
}

结果

执行结果 result : 869

执行结果不一定是869,可能是其他的数,总之就是比正确的结果1000小
原因
result++这个操作的执行过程其实是3个步骤

  1. 读取result变量
  2. 将result变量进行+1
  3. 将result值再赋给result变量
    详细的过程需要进行反编译来分析详细的过程,不是本文的重点,我们只需要知道这个三个过程就行

Synchronized

特性

  • 互斥性:保证同一时刻只能有允许一个线程持有锁(对象或者静态类范围),通过这种多线程协调机制,保证其他线程必须等待该持有锁的线程执行完自己的任务释放了锁后,再获得锁的线程才能执行
  • 可见性:保证了获得锁的线程执行后,对于共享变量所做的操作,对于其他获得锁的线程是可见的(即在获得锁时应获得最新共享变量的值)。

作用范围

  • synchronized代码块加到对象上,则锁的范围为此对象
public class SynchronizedCase2 {
    private static Integer result = 0;
    
    public static void main(String[] args) {
    	//要加锁的对象
        Object object = new Object();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                synchronized (object) {
                    for (int j = 0; j < 100; j++) {
                        result++;
                    }
                }
            }).start();
        }
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("执行结果 result : " + result);
    }
}
  • synchronized加在方法上,则锁的范围对调用方法的this对象
public class SynchronizedCase3 {
    private static Integer result = 0;
    
    public void increment(){
        for (int j = 0; j < 100; j++) {
            result++;
        }
    }
    
    public static void main(String[] args) {
        SynchronizedCase3 synchronizedCase3 = new SynchronizedCase3();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                synchronizedCase3.increment();
            }).start();
        }
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("执行结果 result : " + result);
    }
}
  • synchronized代码块加到class上,则锁的范围为此类
public class SynchronizedCase4 {
    private static Integer result = 0;
    
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                synchronized (SynchronizedCase4.class) {
                    for (int j = 0; j < 100; j++) {
                        result++;
                    }
                }
            }).start();
        }
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("执行结果 result : " + result);
    }
}
  • synchronized添加在静态方法上,则锁的范围为此静态方法的类
public class SynchronizedCase5 {
    private static Integer result = 0;
    
    public static synchronized void increment(){
        for (int j = 0; j < 100; j++) {
            result++;
        }
    }
    
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                SynchronizedCase5.increment();
            }).start();
        }
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("执行结果 result : " + result);
    }
}

注意点

  • 一个线程加了synchronized对象锁,另一个线程没有加锁,是否能保证互斥性
public class SynchronizedCase5 {
    private static Integer result = 0;
    
    public static void main(String[] args) {
        Object object = new Object();
        new Thread(() -> {
            synchronized (object) {
                for (int j = 0; j < 50000; j++) {
                    result++;
                }
            }
        }).start();
        new Thread(() -> {
            for (int j = 0; j < 50000; j++) {
                result++;
            }
        }).start();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("执行结果 result : " + result);
    }
}

结果

执行结果 result : 60859

实际结果证明这种情况不能保证线程安全性

  • 一个线程加了synchronized对象锁,另一个线程加synchronized到此class上,是否能保证互斥性
public class SynchronizedCase6 {
    private static Integer result = 0;
    
    public static void main(String[] args) {
        SynchronizedCase6 synchronizedCase6 = new SynchronizedCase6();
        synchronizedCase6.test();
    }
    
    public void test(){
        new Thread(() -> {
            synchronized (this) {
                for (int j = 0; j < 50000; j++) {
                    result++;
                }
            }
        }).start();
        new Thread(() -> {
            synchronized (SynchronizedCase6.class) {
                for (int j = 0; j < 50000; j++) {
                    result++;
                }
            }
        }).start();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("执行结果 result : " + result);
    }
}

结果

执行结果 result : 59847

由于一个线程的锁是在this对象,另一个对象是在class上,不是同一个锁,所以保证不了互斥性文章来源地址https://www.toymoban.com/news/detail-422878.html

到了这里,关于synchronized各种使用场景的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JUC并发编程-线程和进程、Synchronized 和 Lock、生产者和消费者问题

    源码 + 官方文档 面试高频问! java.util 工具包、包、分类 业务:普通的线程代码 Thread Runnable Runnable 没有返回值、效率相比入 Callable 相对较低! 线程、进程,如果不能使用一句话说出来的技术,不扎实! 进程:一个程序,QQ.exe Music.exe 程序的集合; 一个进程往往可以包含多

    2024年01月20日
    浏览(50)
  • (线程池)多线程使用场景--es数据批量导入、数据汇总、异步调用;如何控制某个方法允许并发访问线程的数量;对ThreadLocal的理解及实现原理、源码解析、ThreadLocal的内存泄露问题

    CountDownLatch(闭锁/倒计时锁) 用来进行线程同步协作,等待所有线程完成倒计时(一个或者多个线程,等待其他多个线程完成某件事情之后才能执行) 其中构造参数用来初始化等待计数值 await() 用来等待计数归零 countDown() 用来让计数 减一 多线程使用场景一:( es数据批量导

    2024年04月25日
    浏览(69)
  • 【liunx】线程池+单例模式+STL,智能指针和线程安全+其他常见的各种锁+读者写者问题

    喜欢的点赞,收藏,关注一下把! 目前我们学了挂起等待锁、条件变量、信号量、生产者消费者模型那我们就根据这些写一个线程池! 线程池: 一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配

    2024年02月02日
    浏览(44)
  • 使用Mybatis生成树形菜单-适用于各种树形场景

    开发中我们难免会遇到各种树形结构展示的场景。比如用户登录系统后菜单的展示,某些大型购物网站商品的分类展示等等,反正开发中会遇到各种树形展示的功能,这些功能大概处理的思路都是一样的,所以本文就总结一下树形结构的代码生成,在开发的时候套用这种结构

    2024年02月08日
    浏览(37)
  • JDBC PrepareStatement 的使用(附各种场景 demo)

    文末有惊喜哦  👇👇👇 在 Java 中,与关系型数据库进行交互是非常常见的任务之一。JDBC(Java Database Connectivity)是 Java 平台的一个标准 API,用于连接和操作各种关系型数据库。其中,PreparedStatement 是 JDBC 中的一个重要接口,用于执行预编译的 SQL 语句。 1)PreparedStatement 继

    2024年01月22日
    浏览(38)
  • java版opencv之Javacv各种场景使用案例

    基于opencv实现,用于实现图片、音视频处理,视频捕捉处理;多媒体RTMP、HLS拉流推流; 机器学习如图像识别、人脸识别等业务实现。这些特性可能在python实现得可能更好或更适合,但Javacv感觉还是不错的。 ① E:opencvbuildjavaopencv-480.jar 可以通过maven命令直接安装到本地mav

    2024年02月05日
    浏览(44)
  • java线程-synchronized详解

    解决线程原子性问题,最常见的手段就是加锁,Java提供了两种加锁的方式,一个synchronized隐式锁,另外一个是通过J.U.C框架提供的Lock显式加锁。本文主要介绍一个Synchronized的实现方式。 synchronized解决的是多个线程之间访问资源的同步性,synchronized 翻译为中文的意思是

    2024年02月10日
    浏览(46)
  • 【多线程进阶】synchronized 原理

    在前面章节中, 提到了多线程中的锁策略, 那么我们 Java 中的锁 synchronized 背后都采取了哪些锁策略呢? 又是如何进行工作的呢? 本节我们就来谈一谈. 关注收藏, 开始学习吧🧐 在 Java 中, synchronized 具有以下特性(这里以 JDK 1.8 为例): 开始时是乐观锁, 如果锁冲突频繁, 就转换为悲

    2024年02月07日
    浏览(34)
  • Java多线程(二)——synchronized 详解

    目录 1 volatile 1.1保证变量可见性 1.2 不能保证数据的原子性举例 1.3 禁止JVM指令重排序 2 synchronized 2.1 概念及演进 2.2 对象锁和类锁 2.3 synchronized 的用法分类 2.4 synchronized 的用法详解 2.5 synchronized总结+补充 3 synchronized 底层原理 3.1 synchronized 同步语句块的情况

    2024年02月13日
    浏览(43)
  • Synchronized与Java线程的关系

    ​ Java多线程处理任务时,为了线程安全,通常会对共享资源进行加锁,拿到锁的线程才能进行访问共享资源。而加锁方式通过都是Synchronized锁或者Lock锁。 ​ 那么多线程在协同工作的时候,线程状态的变化都与锁对象有关系。 ​ Java采用synchronized、以互斥同步的方式

    2024年02月11日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包