文档章节

多线程学习笔记(八)

scymore
 scymore
发布于 2016/09/07 17:18
字数 1349
阅读 18
收藏 0

注:

    当一个线程执行的代码出现异常时,其所持有的锁会自动释放

    同步不具有继承性

    不在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锁,则可大大提高运行效率.

 

 

 

 

 

© 著作权归作者所有

scymore

scymore

粉丝 6
博文 34
码字总数 22032
作品 0
成都
程序员
私信 提问
Posix多线程编程学习笔记

Posix多线程编程学习笔记(一)—线程基础(1) http://blog.chinaunix.net/u/22935/showart_310711.html Posix多线程编程学习笔记(一)—线程基础(2) http://blog.chinaunix.net/u/2293...

晨曦之光
2012/04/13
238
0

hjimce算法类博文目录 个人博客:http://blog.csdn.net/hjimce 个人qq:1393852684 知乎:https://www.zhihu.com/people/huang-jin-chi-28/activities 一、深度学习 深度学习(七十)darknet...

hjimce
2016/01/24
0
0
《数据分析师八大能力培养》课程能力一和能力二学习作业福利热力来袭!

口碑讲师、白金课程、活跃社群,我们也有最独特的作业福利! 数据分析师八大能力培养课程学习笔记活动热力来袭! 1、课程链接: 数据分析师八大能力培养 https://edu.hellobi.com/course/272...

天善学院
2018/05/16
0
0
Sequence to Sequence学习资料

Sequence to Sequence学习资料 seq2seq学习笔记 - CSDN博客 深度学习方法(八):自然语言处理中的Encoder-Decoder模型,基本Sequence to Sequence模型 - CSDN博客 Sequence to Sequence学习...

致Great
2018/05/21
0
0
java&javaweb学习笔记(汇总)

我的java&javaweb学习笔记(汇总) 笔记分为两大部分:javase和javaweb javase javaweb 笔记内容主要是对一些基础特性和编程细节进行总结整理,适合了解java基础语法,想进一步深入学习的人 gi...

brianway
2016/02/09
3.2K
2

没有更多内容

加载失败,请刷新页面

加载更多

nginx访问日志/日志切割/静态文件过期时间/防盗链

Nginx访问日志主要记录部署在nginx上的网站访问数据,日志格式定义在nginx主配置文件中。 nginx主配置文件:/etc/nginx/nginx.conf 查看nginx主配置文件: ```markup [root@linux ~]# cat /e...

asnfuy
24分钟前
8
0
JS_高程4.变量,作用域和内存问题(2)执行环境及作用域

本文转载于:专业的前端网站➨JS_高程4.变量,作用域和内存问题(2)执行环境及作用域 1.执行环境:执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为,       每个执...

前端老手
28分钟前
5
0
手机迅雷下载的文件,电脑上找不到问题

不知道手机迅雷怎么做到的,手机迅雷下载的文件,手机上可以看的到 但连电脑后, 电脑上看不到文件 . 尝试了打开查看隐藏文件, 但没有效果 . 手机上查询文件权限 也是对的 . 可读,可写, 不隐藏 ...

ol_O_O_lo
30分钟前
5
0
python学习11:Python tuple元组详解

元组是 Python 中另一个重要的序列结构,和列表类似,也是由一系列按特定顺序排序的元素组成。和列表不同的是,列表可以任意操作元素,是可变序列;而元组是不可变序列,即元组中的元素不可以...

太空堡垒185
42分钟前
5
0
Java实现数据结构之线性结构

一、顺序表 顺序表本质是使用数组储存数组的一种数据结构,在计算机的储存中是连续的分配内存的。 下面是我自己使用java实现的简单顺序表结构 package list; public class MyArrayList<E> { ...

daxiongdi
44分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部