java多线程中synchronized同步代码块执行问题

      在高洪岩老师的《java多线程编程核心技术》一书的用同步代码块解决同步方法的弊端一节中(p76页),有这样一句话:“当一个线程访问object的一个synchronized同步代码块时,另一个线程依然可以访问该object对象中的非synchronized(this)同步代码块”。
      我产生一个问题:如果线程A调用object对象中的synchronized同步代码块,线程B调用object对象中的synchronized同步代码块和非同步代码块时,如果A先占用object对象,那么B会跳过synchronized方法,而去执行后边的非同步代码块吗?

所以将书上代码略微修改一下,主要是 Task类。

package com.wang.thread.synblock;

public class Task {
	private String getDate1;
	private String getDate2;
	public  void doLongTimeTask(){
		System.out.println("begin task threadName=" + Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		String privateGetDate1 = "长时间处理任务后从远程返回的值1 threadName=" + Thread.currentThread().getName();
		String privateGetDate2 = "长时间处理任务后从远程返回的值2 threadName=" + Thread.currentThread().getName();
		synchronized (this) {
			System.out.println("执行同步代码块 threadName=" + Thread.currentThread().getName());
			getDate1 = privateGetDate1;
			getDate2 = privateGetDate2;
		}
		{
			System.out.println("执行非同步代码块 threadName=" + Thread.currentThread().getName());
		}
		System.out.println(getDate1);
		System.out.println(getDate2);
		System.out.println("end task threadName=" + Thread.currentThread().getName());
		
    
		
	}
	
	public void doAsyTask(){
    	System.out.println("处理非同步方法 threadName=" + Thread.currentThread().getName());
    }

}

     MyThread1类:

package com.wang.thread.synblock;

public class MyThread1  extends Thread{
    private Task task;
    public MyThread1(Task task){
    	super();
    	this.task = task;
    }
    @Override
    public void run() {
    	// TODO 自动生成的方法存根
    	super.run();
    	CommonUtils.beginTime1 = System.currentTimeMillis();
    	task.doLongTimeTask();
    	CommonUtils.endTime1 = System.currentTimeMillis();
    }
}

    MyThread2类:

package com.wang.thread.synblock;

public class MyThread2 extends Thread {
	private Task task;
	public MyThread2(Task task){
		super();
		this.task = task;
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		super.run();
		CommonUtils.beginTime2 = System.currentTimeMillis();
		task.doLongTimeTask();
		CommonUtils.endTime2 = System.currentTimeMillis();
		task.doAsyTask();
	}

}

Run类:

package com.wang.thread.synblock;

public class Run {
	public static void main(String[] args) {
		Task task = new Task();
		MyThread1 thread1 = new MyThread1(task);
		thread1.start();
		MyThread2 thread2 = new MyThread2(task);
		thread2.start();
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		Long beginTime = CommonUtils.beginTime1;
		Long endTime = CommonUtils.endTime1;
		if(CommonUtils.beginTime2 < CommonUtils.beginTime1){
			beginTime = CommonUtils.beginTime2;
		}
		if(CommonUtils.endTime2 > CommonUtils.endTime1){
			endTime = CommonUtils.endTime2;
		}
		System.out.println("耗时:" + ((endTime - beginTime) / 1000));
	}

}

结果:

begin task threadName=Thread-0
begin task threadName=Thread-1
执行同步代码块 threadName=Thread-1
执行非同步代码块 threadName=Thread-1
长时间处理任务后从远程返回的值1 threadName=Thread-1
长时间处理任务后从远程返回的值2 threadName=Thread-1
执行同步代码块 threadName=Thread-0
执行非同步代码块 threadName=Thread-0
长时间处理任务后从远程返回的值1 threadName=Thread-0
长时间处理任务后从远程返回的值2 threadName=Thread-0
end task threadName=Thread-0
end task threadName=Thread-1
处理非同步方法 threadName=Thread-1
耗时:3

通过结果可以看出,在B线程先占用task对象后,A线程只能等A执行完synchronized同步代码块释放锁之后,才能执行synchronized代码块,而不会跳过synchronized代码块而去执行后面的代码。

至于怎么访问对象中的非synchronized(this)代码块,我就不知道了。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011059021/article/details/80350065
个人分类: 多线程 java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭