线程的同步-同步块
2014-04-30 16:11
113 查看
对于同步,除了同步方法外,还可以使用同步代码块,时候同步代码块会带来比同步方法更好的效果。
追其同步的根本的目的,是控制竞争资源的正确的访问,因此只要在访问竞争资源的时候保证同一时刻只能一个线程访问即可,因此Java引入了同步代码快的策略,以提高性能。
在上个例子的基础上,对oper方法做了改动,由同步方法改为同步代码块模式,程序的执行逻辑并没有问题。
/**
* 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 void oper(int x)
{
try {
Thread.sleep(10L);
synchronized (this)
{
this.cash
+= x;
System.out.println(Thread.currentThread().getName() + "运行结束,增加“" +
x + "”,当前用户账户余额为:" + cash);
}
Thread.sleep(10L);
} catch (InterruptedException
e) {
e.printStackTrace();
}
}
@Override
public String
toString() {
return "User{" +
"code='" +
code + '\'' +
", cash=" +
cash +
'}';
}
}
线程E运行结束,增加“32”,当前用户账户余额为:132
线程B运行结束,增加“-60”,当前用户账户余额为:72
线程D运行结束,增加“-30”,当前用户账户余额为:42
线程F运行结束,增加“21”,当前用户账户余额为:63
线程C运行结束,增加“-80”,当前用户账户余额为:-17
线程A运行结束,增加“20”,当前用户账户余额为:3
Process finished with exit code 0
注意:
在使用synchronized关键字时候,应该尽可能避免在synchronized方法或synchronized块中使用sleep或者yield方法,因为synchronized程序块占有着对象锁,你休息那么其他的线程只能一边等着你醒来执行完了才能执行。不但严重影响效率,也不合逻辑。
同样,在同步程序块内调用yeild方法让出CPU资源也没有意义,因为你占用着锁,其他互斥线程还是无法访问同步程序块。当然与同步程序块无关的线程可以获得更多的执行时间。
追其同步的根本的目的,是控制竞争资源的正确的访问,因此只要在访问竞争资源的时候保证同一时刻只能一个线程访问即可,因此Java引入了同步代码快的策略,以提高性能。
在上个例子的基础上,对oper方法做了改动,由同步方法改为同步代码块模式,程序的执行逻辑并没有问题。
/**
* 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 void oper(int x)
{
try {
Thread.sleep(10L);
synchronized (this)
{
this.cash
+= x;
System.out.println(Thread.currentThread().getName() + "运行结束,增加“" +
x + "”,当前用户账户余额为:" + cash);
}
Thread.sleep(10L);
} catch (InterruptedException
e) {
e.printStackTrace();
}
}
@Override
public String
toString() {
return "User{" +
"code='" +
code + '\'' +
", cash=" +
cash +
'}';
}
}
线程E运行结束,增加“32”,当前用户账户余额为:132
线程B运行结束,增加“-60”,当前用户账户余额为:72
线程D运行结束,增加“-30”,当前用户账户余额为:42
线程F运行结束,增加“21”,当前用户账户余额为:63
线程C运行结束,增加“-80”,当前用户账户余额为:-17
线程A运行结束,增加“20”,当前用户账户余额为:3
Process finished with exit code 0
注意:
在使用synchronized关键字时候,应该尽可能避免在synchronized方法或synchronized块中使用sleep或者yield方法,因为synchronized程序块占有着对象锁,你休息那么其他的线程只能一边等着你醒来执行完了才能执行。不但严重影响效率,也不合逻辑。
同样,在同步程序块内调用yeild方法让出CPU资源也没有意义,因为你占用着锁,其他互斥线程还是无法访问同步程序块。当然与同步程序块无关的线程可以获得更多的执行时间。
相关文章推荐
- 线程与同步之二——互斥量
- 从零学习JAVA多线程(三):线程的同步问题
- C# 线程手册 第三章 使用线程 .NET 对同步的支持
- java 线程之对象的同步和异步
- C#与NET实战 第5章 进程、线程与同步 节选
- 线程的同步
- 依旧是转载来的Thread and Sync In C# (C#中的线程与同步)
- Java线程(八):锁对象Lock-同步问题更完美的处理方式(转)
- Java多线程-线程的同步与锁
- Java线程同步和线程间通信代码和控制线程关闭
- 线程同步之生产者消费者
- Java线程:线程的同步-同步方法
- 多线程三 经典线程同步之关键段CS
- java线程同步中使用自增操作时的注意
- Java多线程-线程的同步与锁
- JAVA线程同步的探究(1)
- python多线程编程(3): 使用互斥锁同步线程
- C#基础之--线程、任务和同步:一、异步委托
- .NET线程的同步和通讯
- Python 中的进程、线程、协程、同步、异步、回调