我来教你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/363217.html

(0)
春天春天
上一篇 2023-06-18 17:25
下一篇 2023-06-18 17:25

相关推荐

  • 小编分享CPU的几核几线程是什么意思

    CPU核数即一个CPU由多少个核心组成,核心数越多,代表这个CPU的运转速度越快,性能越好。对于同一个数据处理,一核CPU相当于1个人处理数据,双核CPU相当于2个人处理同一个数据...

    2023-07-12
    0200
  • 我来分享如何实现硬盘对拷。

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

    2023-06-12 PC教程
    0240
  • 教你Win10如何实现Win7任务栏/开始菜单样式。

    Win10如何实现Win7任务栏/开始菜单样式?很多用户升级Win10系统之后,对于Win7系统的任务栏和开始菜单样式甚是想念,既然想念,那我们把Win10任务栏和开始菜单样式改成...

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

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

    2023-06-20
    0230
  • 小编分享如何实现单手操控iPhone手机

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

    2023-06-24
    0240
  • 小编分享Win10如何实现透明标题栏

      Win10如何实现透明标题栏?喜欢设置主题颜色的伙伴都知道,窗口标题栏的颜色会随着主题颜色的改变而改变,如果你喜欢透明的标题栏,或者说是朴素的白色,那么你可以按照以下方法进行设...

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

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

    2023-06-20 PC教程
    0260
  • 小编分享如何实现钉钉自动打卡

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

    2023-06-25
    0190
  • 分享进程和线程的区别是什么

    进程和线程的区别是什么?有什么关系?相信大家对于进程都很熟悉了吧,而线程相对于进程而言,是一个更加接近于执行体的概念,为了让大家更好的了解进程和线程,下面给大家介绍进程和线程的区别...

    2023-06-18
    0210
  • 我来分享联想win10改win7如何实现

    对不少新近购买了联想电脑的朋友来说,想要将系统预装的Win10系统改成Win7还是比较困难的,毕竟新机型采用了UEFI模式只能通过修改BIOS才能改装Win10且受Intel七代C...

    2023-07-02 PC教程
    0210
  • 小编教你MATLAB如何实现画图。

    MATLAB是一款商业数学软件,主要的用途是用于算法开发、数据可视化等操作,这款软件主要用于高级技术计算语言和交互式环境下。在使用这款软件的过程中很多朋友表示不知道要如何作图,现在...

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

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

    2023-07-01 PC教程
    0160
  • 我来分享如何实现Excel单元格内换行。

    使用过Excel的人都有遇到这样的情况,就是偶尔会输入比较长的内容,但有希望可以在一个单元格中显示。Excel没有换行的命令,直接用回车键不是在同一单元格内换行而是切换到了它下面的...

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

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

    2023-05-25 安卓教程
    0260
  • 经验分享爱番番如何实现在线沟通

    爱番番如何实现在线沟通?很多小伙伴还不了解,下面小编给大家介绍爱番番实现在线沟通方法,一起来看看吧。 爱番番如何实现在线沟通 爱番番实现在线沟通方法 首先在手机打开“爱番番客户端”...

    2023-05-26 安卓教程
    0140

发表回复

登录后才能评论