Java多线程--synchronized(二)

synchronized 同步语句块

synchronized方法的缺点

直接在方法上加synchronized关键字在某些情况下存在弊端,比如线程A调用同步方法执行长时间任务,那么其他线程将会等待很长时间。

package ch02.test3;
/*
    synchronized 同步代码块
 */
public class Task {
    private String getData1;
    private String getData2;
    public synchronized void doLongTimeTask() {
        try{
            System.out.println("begin task");
            Thread.sleep(3000);
            String tmpGetData1 = "长时间执行任务返回结果1 threadname=" + Thread.currentThread().getName();
            String tmpGetData2 = "长时间执行任务返回结果2 threadname=" + Thread.currentThread().getName();
            getData1 = tmpGetData1;
            getData2 = tmpGetData2;
            System.out.println(getData1);
            System.out.println(getData2);
            System.out.println("end task");
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class CommonUtils {
    public static long beginTime1;
    public static long endTime1;
    public static long beginTime2;
    public static long endTime2;
}

class MyThread1 extends Thread {
    private Task task;

    public MyThread1(Task task) {
        this.task = task;
    }

    @Override
    public void run() {
        super.run();
        CommonUtils.beginTime1 = System.currentTimeMillis();
        this.task.doLongTimeTask();
        CommonUtils.endTime1 = System.currentTimeMillis();
    }
}

class MyThread2 extends Thread {
    private Task task;

    public MyThread2(Task task) {
        this.task = task;
    }

    @Override
    public void run() {
        super.run();
        CommonUtils.beginTime2 = System.currentTimeMillis();
        this.task.doLongTimeTask();
        CommonUtils.endTime2 = System.currentTimeMillis();
    }
}

class Run {
    public static void main(String[] args) {
        Task task = new Task();
        MyThread1 myThread1 = new MyThread1(task);
        myThread1.start();
        MyThread2 myThread2 = new MyThread2(task);
        myThread2.start();

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long beginTime = Math.min(CommonUtils.beginTime1, CommonUtils.beginTime2);
        long endTime = Math.max(CommonUtils.endTime1, CommonUtils.endTime2);
        System.out.println("总耗时:"+ (endTime - beginTime) / 1000 + "s");
    }
}

output:

begin task
长时间执行任务返回结果1 threadname=Thread-0
长时间执行任务返回结果2 threadname=Thread-0
end task
begin task
长时间执行任务返回结果1 threadname=Thread-1
长时间执行任务返回结果2 threadname=Thread-1
end task
总耗时:6s

synchronized同步代码块的使用

修改doLongTimeTask()方法,去掉方法上的synchronized,在其中添加同步代码块:

public void doLongTimeTask() {
        try{
            System.out.println("begin task");
            Thread.sleep(3000);
            String tmpGetData1 = "长时间执行任务返回结果1 threadname=" + Thread.currentThread().getName();
            String tmpGetData2 = "长时间执行任务返回结果2 threadname=" + Thread.currentThread().getName();
            synchronized (this) {
                getData1 = tmpGetData1;
                getData2 = tmpGetData2;
            }
            System.out.println(getData1);
            System.out.println(getData2);
            System.out.println("end task");
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

output:

begin task
begin task
长时间执行任务返回结果1 threadname=Thread-1
长时间执行任务返回结果2 threadname=Thread-0
end task
长时间执行任务返回结果1 threadname=Thread-0
长时间执行任务返回结果2 threadname=Thread-0
end task
总耗时:3s

当一个线程访问同步代码块时,其他线程仍然可以访问该对象的非同步代码块
方法中线程在synchronized (this) 同步代码块是同步的,不在同步代码块的部分是异步的

  • 和synchronized方法相似,当一个线程访问anyObject对象的synchronized(this)同步代码块时,其他线程中所有同步代码块的访问将被阻塞,说明synchronized使用的“对象监视器”是一个。

小结

  1. synchronized同步方法
    1.1 同一时间只能有一个线程执行synchronized同步方法。
    1.2 对同一对象的所有其他synchronized同步方法和synchronized(this)同步代码块调用呈阻塞状态。
  2. synchronized(this)同步代码块同步代码块
    1.1 同一时间只能有一个线程执行synchronized(this)同步代码块。
    1.2 对同一对象的所有其他synchronized同步方法和synchronized(this)同步代码块调用呈阻塞状态。

作者:lykxbg —— 来一块小饼干

出处:http://www.cnblogs.com/lykxbg/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/lykxbg/p/13650380.html