注:
当一个线程执行的代码出现异常时,其所持有的锁会自动释放
同步不具有继承性
不在synchronized块中就是一部执行,在synchronized中就是同步执行
和synchronized方法一样,synchronized(this)代码块也是锁定当前对象的
1. 同步的弊端
public class CommonUtils {
public static long startTime1;
public static long endTime1;
public static long startTime2;
public static long endTime2;
}
public class DemeritOfSynchronized {
private String username;
private String password;
public synchronized void test() {
try{
System.out.println("begin the test");
Thread.sleep(3000);
username = "username is " + Thread.currentThread().getName();
password = "password is " + System.currentTimeMillis();
System.out.println(username);
System.out.println(password);
System.out.println("end the test");
}catch (Exception e){
e.printStackTrace();
}
}
}
public class FirstThread extends Thread {
private DemeritOfSynchronized demeritOfSynchronized;
public FirstThread(DemeritOfSynchronized demeritOfSynchronized) {
super();
this.demeritOfSynchronized = demeritOfSynchronized;
}
@Override
public void run() {
super.run();
CommonUtils.startTime1 = System.currentTimeMillis();
demeritOfSynchronized.test();
CommonUtils.endTime1 = System.currentTimeMillis();
}
}
public class SecondThread extends Thread {
private DemeritOfSynchronized demeritOfSynchronized;
public SecondThread(DemeritOfSynchronized demeritOfSynchronized) {
super();
this.demeritOfSynchronized = demeritOfSynchronized;
}
@Override
public void run() {
super.run();
CommonUtils.startTime2 = System.currentTimeMillis();
demeritOfSynchronized.test();
CommonUtils.endTime2 = System.currentTimeMillis();
}
}
public class Run {
public static void main(String[] args) {
DemeritOfSynchronized demeritOfSynchronized = new DemeritOfSynchronized();
FirstThread firstThread = new FirstThread(demeritOfSynchronized);
firstThread.start();
SecondThread secondThread = new SecondThread(demeritOfSynchronized);
secondThread.start();
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
long beginTime = CommonUtils.startTime1;
if (CommonUtils.startTime2 < CommonUtils.startTime1) {
beginTime = CommonUtils.startTime2;
}
long endTime = CommonUtils.endTime2;
if (CommonUtils.endTime1 > CommonUtils.endTime2) {
endTime = CommonUtils.endTime1;
}
System.out.println("spend time " + (endTime - beginTime) / 1000);
}
}
运行结果:

2. 同步代码块的使用
当两个并发线程访问同一个对象的object中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行名一个线程必须等待当前线程执行完这个代码块之后才能执行改代码块.
public class ServiceMethod {
public void ServiceMethod() {
try {
synchronized (this){
System.out.println("begin time = " + System.currentTimeMillis());
Thread.sleep(2222);
System.out.println("end time = " + System.currentTimeMillis());
}
}catch (Exception e){
e.printStackTrace();
}
}
}
public class FirstThread extends Thread {
private ServiceMethod serviceMethod;
public FirstThread(ServiceMethod serviceMethod){
super();
this.serviceMethod = serviceMethod;
}
@Override
public void run(){
super.run();
serviceMethod.ServiceMethod();
}
}
public class SecondThread extends Thread {
private ServiceMethod serviceMethod;
public SecondThread(ServiceMethod serviceMethod){
super();
this.serviceMethod = serviceMethod;
}
@Override
public void run(){
super.run();
serviceMethod.ServiceMethod();
}
}
public class Run {
public static void main(String[] args){
ServiceMethod serviceMethod = new ServiceMethod();
FirstThread firstThread = new FirstThread(serviceMethod);
firstThread.start();
SecondThread secondThread = new SecondThread(serviceMethod);
secondThread.start();
}
}
运行结果:

3.用同步代码块解决同步方法的弊端
将1中的DemeritOfSynchronized方法代码修改为
public class DemeritOfSynchronized {
private String username;
private String password;
public void test() {
try{
System.out.println("begin the test");
Thread.sleep(3000);
synchronized (this){
username = "username is " + Thread.currentThread().getName();
password = "password is " + System.currentTimeMillis();
}
System.out.println(username);
System.out.println(password);
System.out.println("end the test");
}catch (Exception e){
e.printStackTrace();
}
}
}
运行结果:

4.synchronized代码块之间的同步性
在使用synchronized(this)代码块时需要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object对象中所有其他synchronized(this)同步代码块的访问将被阻塞,这说明synchronized使用的对象监视器是一个.
public class SynchronizedCodes {
public void SynchronizedCodes() {
try {
synchronized (this) {
System.out.println("A begin time = " + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("A end time = " + System.currentTimeMillis());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void SynchronizedCodesB() {
synchronized (this) {
System.out.println("B begin time = " + System.currentTimeMillis());
System.out.println("B end time = " + System.currentTimeMillis());
}
}
}
public class FirstThread extends Thread{
SynchronizedCodes synchronizedCodes = new SynchronizedCodes();
public FirstThread(SynchronizedCodes synchronizedCodes){
super();
this.synchronizedCodes = synchronizedCodes;
}
@Override
public void run(){
super.run();
synchronizedCodes.SynchronizedCodes();
}
}
public class SecondThread extends Thread{
SynchronizedCodes synchronizedCodes = new SynchronizedCodes();
public SecondThread(SynchronizedCodes synchronizedCodes){
super();
this.synchronizedCodes = synchronizedCodes;
}
@Override
public void run(){
super.run();
synchronizedCodes.SynchronizedCodesB();
}
}
public class Run {
public static void main(String[] args){
SynchronizedCodes synchronizedCodes = new SynchronizedCodes();
FirstThread firstThread = new FirstThread(synchronizedCodes);
firstThread.start();
SecondThread secondThread = new SecondThread(synchronizedCodes);
secondThread.start();
}
}
运行结果:

5. 将任意对象作为对象监视器
多个线程调用同一个对象中的不同名称的synchronized同步方法或synchronized(this)同步代码块时,调用的效果就是按顺序执行,也就是同步的,阻塞的.
1) synchronized同步方法
①对其他synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态.
②同一时间只有一个线程可以执行synchronized同步方法中的代码.
2) synchronized(this)同步代码块
①对其他synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态.
②同一时间只有一个线程可以执行synchronized(this)同步代码块中的代码
在前面的学习中,使用synchronized(this)格式来同步代码块,其实java还支持对任意对象作为对象监视器来实现同步的功能,这个任意对象大多数是实例变量及方法的参数,使用格式为synchronized(非this对象).
根据前面对synchronized(this)同步代码块的作用总结可知,synchronized(非this对象)格式的作用只有1种:synchronized(非this对象x同步代码块).
1)在多个线程持用对象监视器为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象x)同步代码块中的代码.
2)当持有对象监视器为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象x)同步代码块中的代码.
public class SynchronizedByAnyString {
private String username;
private String password;
private String anyString = new String();
public void setUsernamAndPassword(String user, String pswd) {
try {
synchronized (anyString) {
System.out.println("The Thread is " + Thread.currentThread().getName() + " enter time is " + System.currentTimeMillis());
username = user;
Thread.sleep(2000);
password = pswd;
System.out.println("The Thread is " + Thread.currentThread().getName() + " leave time is " + System.currentTimeMillis());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class FirstThread extends Thread{
SynchronizedByAnyString synchronizedByAnyString = new SynchronizedByAnyString();
public FirstThread(SynchronizedByAnyString synchronizedByAnyString){
super();
this.synchronizedByAnyString = synchronizedByAnyString;
}
@Override
public void run(){
super.run();
synchronizedByAnyString.setUsernamAndPassword("scymore","scymorePassword");
}
}
public class SecondThread extends Thread{
SynchronizedByAnyString synchronizedByAnyString = new SynchronizedByAnyString();
public SecondThread(SynchronizedByAnyString synchronizedByAnyString){
super();
this.synchronizedByAnyString = synchronizedByAnyString;
}
@Override
public void run(){
super.run();
synchronizedByAnyString.setUsernamAndPassword("b","bbbb");
}
}
public class Run {
public static void main(String[] args){
SynchronizedByAnyString synchronizedByAnyString = new SynchronizedByAnyString();
FirstThread firstThread = new FirstThread(synchronizedByAnyString);
firstThread.setName("firstThread");
firstThread.start();
SecondThread secondThread = new SecondThread(synchronizedByAnyString);
secondThread.setName("secondThread");
secondThread.start();
}
}
运行结果:

锁非this对象具有一定的优点:如果在一个类中有很多个synchronized方法,这是虽然能实现同步,但会受到阻塞,所以影响运行效率;但如果使用同步代码块锁非this对象,则synchronized(非this)代码块中的程序与同步方法是异步的,不与其他锁this同步方法争抢this锁,则可大大提高运行效率.
来源:oschina
链接:https://my.oschina.net/u/2310587/blog/743794