分享Java如何实现线程同步。

Java线程同步是保证多线程状态下安全访问竞争资源的一种编程手段,但线程的同步在Java多线程编程中算是一个比较难的难点,很多开发者甚至都不知道什么是竞争资源,也不知道时候需要进行线程同步,当然这是没有明确答案的,一些原则问题还是要考虑。

Java如何实现线程同步?线程同步的方法和反面教材

Java如何实现线程同步?

对于同步,在具体的Java代码中需要完成一下两个操作:

1、把竞争访问的资源标识为private;

2、同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。

当然这不是唯一控制并发安全的途径。

synchronized 关键字使用说明

synchronized 只能标记非抽象的方法,不能标识成员变量。

为了演示同步方法的使用,构建了一个信用卡账户,起初信用额为100w,然后模拟透支、存款等多个操作。显然银行账户User对象是个竞争资源,而多个并发操作的是账户方法oper(int x),当然应该在此方法上加上同步,并将账户的余额设为私有变量,禁止直接访问。

01/**02* Java线程:线程的同步03*04* @author leizhimin 2009-11-4 11:23:3205*/06public class Test {07public static void main(String[] args) {08User u = new User("张三", 100);09MyThread t1 = new MyThread("线程A", u, 20);10MyThread t2 = new MyThread("线程B", u, -60);11MyThread t3 = new MyThread("线程C", u, -80);12MyThread t4 = new MyThread("线程D", u, -30);13MyThread t5 = new MyThread("线程E", u, 32);14MyThread t6 = new MyThread("线程F", u, 21);15t1.start();16t2.start();17t3.start();18t4.start();19t5.start();20t6.start();21}22}23class MyThread extends Thread {24private User u;25private int y = 0;26MyThread(String name, User u, int y) {27super(name);28this.u = u;29this.y = y;30}31public void run() {32u.oper(y);33}34}35class User {36private String code;37private int cash;38User(String code, int cash) {39this.code = code;40this.cash = cash;41}42public String getCode() {43return code;44}45public void setCode(String code) {46this.code = code;47}48/**49* 业务方法50* @param x 添加x万元51*/52public synchronized void oper(int x) {53try {54Thread.sleep(10L);55this.cash += x;56System.out.println(Thread.currentThread().getName() + "运行结束,增加“" + x + "”,当前用户账户余额为:" + cash);57Thread.sleep(10L);58} catch (InterruptedException e) {59e.printStackTrace();60}61}62@Override63public String toString() {64return "User{" +65"code='" + code + ''' +66", cash=" + cash +67'}';68}69}复制代码/*** Java线程:线程的同步** @author leizhimin 2009-11-4 11:23:32*/public class Test {public static void main(String[] args) {User u = new User("张三", 100);MyThread t1 = new MyThread("线程A", u, 20);MyThread t2 = new MyThread("线程B", u, -60);MyThread t3 = new MyThread("线程C", u, -80);MyThread t4 = new MyThread("线程D", u, -30);MyThread t5 = new MyThread("线程E", u, 32);MyThread t6 = new MyThread("线程F", u, 21);t1.start();t2.start();t3.start();t4.start();t5.start();t6.start();}}class MyThread extends Thread {private User u;private int y = 0;MyThread(String name, User u, int y) {super(name);this.u = u;this.y = y;}public void run() {u.oper(y);}}class User {private String code;private int cash;User(String code, int cash) {this.code = code;this.cash = cash;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}/*** 业务方法* @param x 添加x万元*/public synchronized void oper(int x) {try {Thread.sleep(10L);this.cash += x;System.out.println(Thread.currentThread().getName() + "运行结束,增加“" + x + "”,当前用户账户余额为:" + cash);Thread.sleep(10L);} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic String toString() {return "User{" +"code='" + code + ''' +", cash=" + cash +'}';}}

输出结果:

01线程A运行结束,增加“20”,当前用户账户余额为:12002线程F运行结束,增加“21”,当前用户账户余额为:14103线程E运行结束,增加“32”,当前用户账户余额为:17304线程C运行结束,增加“-80”,当前用户账户余额为:9305线程B运行结束,增加“-60”,当前用户账户余额为:3306线程D运行结束,增加“-30”,当前用户账户余额为:307Process finished with exit code 0复制代码线程A运行结束,增加“20”,当前用户账户余额为:120线程F运行结束,增加“21”,当前用户账户余额为:141线程E运行结束,增加“32”,当前用户账户余额为:173线程C运行结束,增加“-80”,当前用户账户余额为:93线程B运行结束,增加“-60”,当前用户账户余额为:33线程D运行结束,增加“-30”,当前用户账户余额为:3Process finished with exit code 0

反面教材,不同步的情况,也就是去掉oper(int x)方法的synchronized修饰符,然后运行程序,结果如下:

01线程A运行结束,增加“20”,当前用户账户余额为:6102线程D运行结束,增加“-30”,当前用户账户余额为:6303线程B运行结束,增加“-60”,当前用户账户余额为:304线程F运行结束,增加“21”,当前用户账户余额为:6105线程E运行结束,增加“32”,当前用户账户余额为:9306线程C运行结束,增加“-80”,当前用户账户余额为:6107Process finished with exit code 0复制代码线程A运行结束,增加“20”,当前用户账户余额为:61线程D运行结束,增加“-30”,当前用户账户余额为:63线程B运行结束,增加“-60”,当前用户账户余额为:3线程F运行结束,增加“21”,当前用户账户余额为:61线程E运行结束,增加“32”,当前用户账户余额为:93线程C运行结束,增加“-80”,当前用户账户余额为:61Process finished with exit code 0

很显然,上面的结果是错误的,导致错误的原因是多个线程并发访问了竞争资源u,并对u的属性做了改动。

可见同步的重要性。

注意:

通过前文可知,线程退出同步方法时将释放掉方法所属对象的锁,但还应该注意的是,同步方法中还可以使用特定的方法对线程进行调度。这些方法来自于java.lang.Object类。

01void notify()02唤醒在此对象监视器上等待的单个线程。03void notifyAll()04唤醒在此对象监视器上等待的所有线程。05void wait()06导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。07void wait(long timeout)08导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。09void wait(long timeout, int nanos)10导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。复制代码void notify()唤醒在此对象监视器上等待的单个线程。void notifyAll()唤醒在此对象监视器上等待的所有线程。void wait()导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。void wait(long timeout)导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。void wait(long timeout, int nanos)导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

以上步骤便是Java多线程编程中的线程同步用法,为了清楚了解这部分概念,笔者还展示了反面教程的使用,避免用户走更多的弯路。

本文来自网络投稿,来自作者春天。不代表酷牛教程立场,如若转载,请注明出处:https://www.xukn.com/358853.html

(0)
春天春天
上一篇 2023-06-17 02:05
下一篇 2023-06-17 02:06

相关推荐

  • 我来分享Win8如何实现系统自动登陆

    尽管为电脑设置登陆密码可以很大程度上的保护电脑的安全,不过,如果在电脑里面的文件都不是很重要的情况下,电脑设置有登陆密码就显得多余了,并且每次开机都还要输入密码才能登陆也很麻烦。这...

    2023-06-28
    0190
  • 小编分享Win10如何实现电脑语音输入

    不知道大家知不知道,电脑是支持语音输入文字的,每当打字打累的时候,或者不想打字的时候,我们就可以进行电脑语音输入文字。那么,Win10要如何实现电脑语音输入呢?其实方法很简单,下载...

    2023-06-20 PC教程
    0260
  • 我来教你Java如何实现线程同步

    Java线程同步是保证多线程状态下安全访问竞争资源的一种编程手段,但线程的同步在Java多线程编程中算是一个比较难的难点,很多开发者甚至都不知道什么是竞争资源,也不知道时候需要进行...

    2023-06-18
    0220
  • 小编分享Premiere如何实现视频全屏预览

    怎样才能实现视频全屏预览呢?在我们使用Premiere时,有时觉得预览视频太小,不太便于观看。小编今天就为你们带来了Premiere实现视频全屏预览的具体方法步骤。 方法/步骤 1...

    2023-07-02 PC教程
    0230
  • 经验分享百度云手机版如何实现文件秒传(百度云手机版如何实现文件秒传功能)

    百度云手机版实现文件秒传的方法是什么?下面小编就演示一下百度云手机版实现文件秒传的具体操作方法,相信对大家会有所帮助的。 百度云手机版如何实现文件秒传?百度云手机版实现文件秒传的具...

    2023-05-25 安卓教程
    0260
  • 如何实现Excel条件智能标记,简单方法,速学。

    学习是永无止境的,不管是上班还是上学,都是一个学习的过程,至于在这个过程中,你学的多少,学的怎样,这就是你自己的事情了,不管是你的老师,还是你的上级,都是起到一个领路的作用,你肯不...

    2023-05-27 技巧分享
    0170
  • 小编教你Win10如何实现自动关机

    Win10如何实现自动关机?因某些需求不可避免地我们在生活或工作中需要下载大文件,尤其是在夜间下载时。基本上是打开您的计算机, 如果出现点意外不免耽误很多事情 。这在一定程度上增加...

    2023-07-14
    0170
  • 小编分享如何实现单手操控iPhone手机

    如何实现单手操控iPhone手机?很多小伙伴都在抱怨自己用的iPhone手机屏幕太大太难操作,下面,小编就为大家介绍下实现单手操控iPhone手机方法。 我们需要用到iPhone的...

    2023-06-24
    0240
  • 小编分享如何实现钉钉自动打卡

    如何实现钉钉自动打卡?钉软件中提供了一项自动打卡功能,非常人性化,对于经常忘记打卡的用户来说简直就是福音。下面,小编就为大家介绍下实现钉钉自动打卡方法。 实现钉钉自动打卡必须要满足...

    2023-06-25
    0190
  • 教你WiFi共享大师如何实现手机远程控制电脑

    WiFi共享大师如何实现手机远程控制电脑?最近有很多小伙伴在问WIFI共享大师要怎样才能实现手机远程控制电脑,今天小编就带给大家WIFI共享大师让手机控制电脑的具体操作步骤。 方法...

    2023-07-01 PC教程
    0170
  • 我来分享如何实现硬盘对拷。

    随着电脑日益的普及,电脑几乎成了我们生活中不可缺少的一部分了,人们对电脑功能的期望也明显提高。有的时候我们需要将一块硬盘内的资料转移到另一块硬盘上面,实现两个硬盘的资料共享,那两个...

    2023-06-12 PC教程
    0240
  • 我来分享录音啦如何实现录音转文字。

    录音啦这个好用的会议录音软件可以实现将录制下来的人声语音通过智能AI快速转换为文本,方便以后做会议纪要摘录,下面就来教大家如何实现录音转文字的操作。 首先你到注册登陆到软件中,这样...

    2023-06-09 PC教程
    0230
  • 小编教你线程池是什么

    使用线程池的好处有很多,比如节省系统资源的开销,节省创建和销毁线程的时间等,当我们需要处理的任务较多时,就可以使用线程池,可能还有很多用户不知道Java线程池如何使用?下面小编给大...

    2023-06-18
    0200
  • 我来分享Win10如何实现登录系统时自动更新升级病毒库

    Win10如何实现登录系统时自动更新升级病毒库?Windows Defender是Windows系统自带的杀毒软件,我们可以让Windows Defender在登录系统时自动更新升...

    2023-06-20
    0230
  • 小编分享如何实现硬盘对拷

    硬盘对拷,也就是将其中一个硬盘的分区表、引导文件、启动BOOT、隐藏文件等数据拷贝到另一个硬盘中的方法,这个过程和复制粘贴类似,但并非简单的复制粘贴,面对该问题的网友大概是已经买好...

    2023-06-18 PC教程
    0230

发表回复

登录后才能评论