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="cash67'}';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修饰符 , 然后运行程序 , 结果如下:

推荐阅读