实现线程同步的几种方法

2023-10-31

  • 在多线程程序中,会出现多个线程抢占一个资源的情况,这时间有可能会造成冲突,也就是一个线程可能还没来得及将更改的 资源保存,另一个线程的更改就开始了。可能造成数据不一致。因此引入多线程同步,也就是说多个线程只能一个对共享的资源进行更改,其他线程不能对数据进行修改。
  • 1.如下一个两个线程对一个银行账户进行存钱的小实例,其中使用synchornized修饰方法实现线程的同步
  • 代码如下:
class bank{
	private int count=100;
	public synchronized void dispit() {
		  count+=10;
	}
	public int getcount() {
		return count;
	}
}
class ThreadCount extends Thread{
	private bank count;
	private JTextArea textarea = new JTextArea();
	public ThreadCount(bank count,JTextArea textarea) {
		this.count = count;
		this.textarea = textarea;
	}
	public void run() {
		for(int i=0; i<10; i++) {
			count.dispit();
			textarea.append("账户余额为:"+count.getcount()+"\n");
		}
	}
}

2.同步是一种高开销的操作,因此应该尽量减少同步内容,因此也可以使用修饰代码块来代替修饰整个方法。

class bank{
	private int count=100;
	public void dispit() {
		synchronized(this) {
		  count+=10;
		}
	}
	public int getcount() {
		return count;
	}
}
class ThreadCount extends Thread{
	private bank count;
	private JTextArea textarea = new JTextArea();
	public ThreadCount(bank count,JTextArea textarea) {
		this.count = count;
		this.textarea = textarea;
	}
	public void run() {
		for(int i=0; i<10; i++) {
			count.dispit();
			textarea.append("账户余额为:"+count.getcount()+"\n");
		}
	}
}

3.使用volatile修饰数据,对于当下问题,只用使用volatile来修饰账户的余额变量即可。该修饰词是对域变量的访问提供了以这种防锁机制,相当于告诉虚拟机,该域的变量可能被更改。因此每次使用该域都要重新计算,而不是从寄存器中取出数据。从而实现线程的同步。该修饰词不能修改final类型变量

class bank{
	private volatile int count=100;
	public void dispit() {
		  count+=10;
	}
	public int getcount() {
		return count;
	}
}
class ThreadCount extends Thread{
	private bank count;
	private JTextArea textarea = new JTextArea();
	public ThreadCount(bank count,JTextArea textarea) {
		this.count = count;
		this.textarea = textarea;
	}
	public void run() {
		for(int i=0; i<10; i++) {
			count.dispit();
			textarea.append("账户余额为:"+count.getcount()+"\n");
		}
	}
}

4.使用重入锁实现线程同步。使用类ReentrantLock类来定义锁,其中lock()方法为打开锁,unlock()方法为关闭锁
类似于synchronized修饰方法有一样功能。使用锁时间需要注意应该及时放开锁,不然会进入死锁状态。一般是在finally中释放锁

class bank{
	private volatile int count=100;
	private Lock lock = new ReentrantLock();
	public void dispit() {
		 lock.lock();
		 try {
		  count+=10;
		 }finally{
			 lock.unlock();
		 }
	}
	public int getcount() {
		return count;
	}
}
class ThreadCount extends Thread{
	private bank count;
	private JTextArea textarea = new JTextArea();
	public ThreadCount(bank count,JTextArea textarea) {
		this.count = count;
		this.textarea = textarea;
	}
	public void run() {
		for(int i=0; i<10; i++) {
			count.dispit();
			textarea.append("账户余额为:"+count.getcount()+"\n");
		}
	}
}

代码的输出结果如下:
在这里插入图片描述
可以看到,每次增加10 的时间只有一个线程在进行,也就是线程的同步

5.使用ThreadLocal类来管理。不过该方法和同步机制不相同。该类管理的变量在每个线程中都有自己的副本,副本之间相互独立,因此获得的结果和其他不同。

class bank{
	private static ThreadLocal<Integer> count = new ThreadLocal() {
	   protected Integer initialValue() {
		   return 100;
	   }
	};
	private Lock lock = new ReentrantLock();
	public void dispit() {
		 lock.lock();
		 try {
		  count.set(count.get()+10);
		 }finally{
			 lock.unlock();
		 }
	}
	public int getcount() {
		return count.get();
	}
}

class ThreadCount extends Thread{
	private bank count;
	private JTextArea textarea = new JTextArea();
	public ThreadCount(bank count,JTextArea textarea) {
		this.count = count;
		this.textarea = textarea;
	}
	public void run() {
		for(int i=0; i<10; i++) {
			count.dispit();
			textarea.append("账户余额为:"+count.getcount()+"\n");
		}
	}
}

结果如图:
在这里插入图片描述
可以看到,在改程序中,好比两个账户相互独立,互不干扰一样。同样解决了相同的变量访问冲突问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实现线程同步的几种方法 的相关文章

  • 是面试官放水,还是公司实在是太缺人?这都没挂,腾讯原来这么容易进···

    本人211非科班 之前在字节和腾讯实习过 这次其实没抱着什么特别大的希望投递 没想到腾讯可以再给我一次机会 还是挺开心的 本来以为有个机会就不错啦 没想到能成功上岸 在这里要特别感谢帮我内推的同学 中间投递比较曲折 是他帮了我很多 非常负责
  • ARM64架构-Ubuntu20更换国内镜像源

    前言 在嵌入式开发中 常用到ARM64的开发平台 进行下载东西时想换国内源 下面以中科大源为参考 一 什么是源 其实吧它就像苹果和案桌的软件应用商店一样 为Linux用户提供软件下载及更新服务的 Linux家族有三个软件源系统 yum源 使
  • 逆向crackme之ESp定律脱壳

    1 前言 此题来自攻防世界高手进阶区的一道逆向题目 crackme 通过对可执行程序进行脱壳 该壳为北斗的壳 涉及到ESP定律 大体流程是找到call处的ESp 在数据窗口中跟随 下个硬件访问断点 就到了OEP处 用ODdump脱壳就行了
  • 使用Docker高效搭建开发环境(详细教程)

    在学习Docker镜像和容器之前 先给大家介绍下Docker的概念 在理解概念的基础上可以举一反三 1 Docker的核心为镜像和容器 有JAVA基础的小伙伴们可以理解为镜像就是JAVA中的类 容器为相关类的对象 一个镜像可以创建多个容器
  • ffmpeg快速将mkv转mp4

    想用pr来剪一些动漫视频 视频是mkv格式的 但是我的pr pro2021不支持mkv格式 只能先转成mp4格式再用pr剪切 ffmpeg的格式转换是最快的 官网下载ffmpeg https github com BtbN FFmpeg B
  • 【环境搭建】(二)在Ubuntu22.04安装/卸载软件Anaconda

    一个愿意伫立在巨人肩膀上的农民 1 Anaconda的主要功能 Anaconda是一个Python环境管理工具 因为不同的Python项目中可能需要同一个库的不同版本 为了避免冲突 Anaconda可以对不同Python项目创建自己的运行环
  • 生活笑话

    n多年前 传呼机还算比较稀罕的时候 有师兄A买了传呼机 师兄B说 要试一试看 好使不 遂打电话到呼台 小姐 请呼 站在那里不要动 等我们过去打你 小姐大惊 这种信息我们不能发 B师兄坚持 就得这么发 不一会儿 呼机响起 拿起一看 有人要打你
  • 详细讲述C++各种运算符重载

    详细讲述C 各种运算符重载 1 等号运算符重载 2 加号运算符重载 3 取地址运算符重载 4 前置 后置 运算符重载 4 1后置 的引用问题 4 2相关问题分析 5 重载类型强转运算符 6 括号运算符重载 7 输出运算符重载 8 星号运算符
  • jetbrains phpstorm插件开发环境搭建

    2018 04 14 重要更新 使用 gradle 进行构建可以免去下面大部分步骤 使用 gradle 我们仅需下载安装 JDK Idea 使用 gradle 的方法是 新建 Project 然后选择如下 使用 gradle 的好处是 不用
  • C++多态(虚函数)使用详解

    目录 1 什么是多态 1 1父类指针指向子类指针案例 2 多态 虚函数的基本使用 3 多态 虚函数表 3 1单个类的虚函数表 3 2使用继承的虚函数表 3 3多重继承的虚函数表 4 虚函数的修饰 4 1虚函数的修饰 final 4 2虚函数
  • windows 更改pip源

    在c user 或者用户 电脑的用户名 目录下创建一个命名为 pip 的文件夹 如 C Users Administrator pip 在该文件夹下创建一个命名为 pip ini 的文件 在该文件中写入以下内容 global index u
  • SpringBoot之定时任务详解

    使用SpringBoot创建定时任务 目前主要有以下三种创建方式 一 基于注解 Scheduled 二 基于接口 SchedulingConfigurer 前者相信大家都很熟悉 但是实际使用中我们往往想从数据库中读取指定时间来动态执行定时任
  • 客观面试题--37.Spring/SpringMVC常用注解有哪些?

    Spring常用注解 使用注解来构造IoC容器 用注解来向Spring容器注册Bean 需要在applicationContext xml中注册
  • Microsoft Exchange ProxyShell Remote Code Execution CVE-2021-34473 (Metasploit exploits)分析

    CVE 2021 34473 加载winrm模块文件 Windows专用链接对象 https github com WinRb WinRM require winrm class MetasploitModule lt Msf Exploi
  • gdb调试,splint_valgrind代码检查

    文章目录 基本调试命令 语法 为什么没有产生core 文件 一 GDB 1 test 2 常用命令 3 使用core 二 代码检查 1 splint 2 valgrind 常见错误 命令格式 test1 test2 编译一个多种内存使用错误
  • Minor GC 过程

    如果Eden空间占满了 会触发 minor GC Minor GC后仍然存活的对象会被复制到S0中去 这样Eden就被清空可以分配给新的对象 又触发了一次 Minor GC S0和Eden中存活的对象被复制到S1中 并且S0和Eden被清空
  • TypeScript 最快速的入门教程

    TypeScript 最快速的入门教程 在线阅读 https niexia github io typescript tutorial 英文原版 https www typescripttutorial net 如果对你有帮助 欢迎在 gi
  • HarmonyOS开发详解(二)——鸿蒙开发体系详解及入门实例演示运行

    本篇文章的计划 先体系的介绍一下鸿蒙开发相关的体系内容 希望通过本篇内容构建对鸿蒙开发体系的了解 最后再来一个最简单入门例子 既是自我的学习 也希望对你了解鸿蒙开发的全貌有帮助 这样安排而没有直接写一个Helloworld例子的原因 很多朋
  • Leetcode 剑指Offer

    求 1 2 n 要求不能使用乘除法 for while if else switch case等关键字及条件判断语句 A B C 示例 1 输入 n 3 输出 6 示例 2 输入 n 9 输出 45 一 信息 1 求一个等差数列的求和 2

随机推荐