您的位置:首页 > 编程语言 > Java开发

Java多线程编程——synchronized用法总结

2017-11-07 16:21 459 查看
在Java多线程编程的问题中,“线程安全”和“非线程安全”问题成为整个多线程编程的核心思考问题,其中主要涉及到多个线程对共享变量访问时可能出现的各种错误,通过synchronized的使用机制,以最小程度的实现部分代码的同步执行。Java通过提供synchronized机制,来实现同步。由于synchronized的使用过于的灵活,因此,本文主要对synchronized的一些用法、锁对象和相关问题进行了总结。

synchronized的用法大体上可分为两类,其一,synchronized通过直接修饰类方法,实现同步;其二,synchronized通过构成同步代码块来实现代码块里的程序的同步性。

a. synchronized通过直接修饰类方法

synchronized public void addI(String username) {
if(username.equals("a")) {
num = 100;
System.out.println("a set over");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
num = 200;
System.out.println("b set over");
}
System.out.println(username + " num="+num);
}特点:synchronized通过修饰非静态方法,可使多线程访问该方法时,获得基于对象的锁,从而实现同步的对该方法进行访问
优点:能够实现方法的同步性,从而确保方法的执行不会由于多线程的访问而导致错误的发生

缺点:由于同步访问将导致执行效率的下降,计算机的吞吐率下降,多线程执行时间将更长

注:当synchronized修饰的类方法为静态方法,即由static进行修饰的方法时,线程将获得基于类的锁,即其余未获得锁的线程将无法访问该类的任何部分。区别:当修饰的类方法不是static修饰的方法时,其余线程可访问非同步(synchronized修饰)的方法。

只要对象不变,即使对象的属性被改变,运行的结果还是同步

重要结论:

1. synchronized关键字加到static静态方法上是给Class类上锁,而synchronized关键字加到非static静态方法上是给对象上锁

2. 只有共享资源的读写访问才需要同步化,如果不是共享资源,那么根本就没有同步的必要

b. synchronized同步代码块

public void doLongTimeTask() {
for(int i = 0; i < 100; i++) {
System.out.println("nosynchronized threadName="+Thread.currentThread().getName()+" i="+(i+1));
}
System.out.println("");
synchronized(this) {
for(int i = 0; i < 100; i++) {
System.out.println("synchronized threadName="+Thread.currentThread().getName()+" i="+(i+1));
}
}
}该例可看出,相对于synchronized修饰类方法,synchronized同步块能够进一步缩小同步代码的范围,从而保证更多部分的代码是异步执行的,从而很好的保证了多线程下的高资源利用率以及系统的吞吐量
在synchronized同步代码块中,利用synchronized(Object){}该同步形式,可以灵活的对不同的对象Object进行锁限制,通过控制共享变量object来实现不同的同步,由此可能产生死锁问题

public void run() {
if(username.equals("a")) {
synchronized(lock1) {
System.out.println("username = "+username);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(lock2) {
System.out.println("按lock1->lock2代码顺序执行了");
}
}
}
if(username.equals("b")) {
synchronized(lock2) {
System.out.println("username = "+username);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized(lock1) {
System.out.println("按lock2->lock1代码顺序执行了");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息