读书笔记-java网络编程-3线程-同步

46 篇文章 0 订阅
17 篇文章 0 订阅

3. 同步

当不同的进程方法同一个资源的时候,只有一个进程可以获得资源的访问权限,而其他进程将要继续阻塞。

3.1同步块

        synchronized (System.out) {
            System.out.print(input+":");
            System.out.print(DatatypeConverter.printHexBinary(digest));
            System.out.println();
        }

使用Synchronized将需要同步的资源括起来,在大括号内的程序将会同步,不会并行执行。但是需要注意的这样只能纺织同一个对象同步的其他线程 使用这个共享资源,但是如果是其他类或者其他进程却是有可能并行执行的,需要尤其关注这一点。

通常来说选择资源的方式有两种:
1. 可以对需要同步的资源同步,比如对System.out同步。
2. 可以对该类对象本身同步也就是this。

3.1 同步方法

由于对对象某个方法同步非常常见,因此java提供了一种synchronized修饰符,对对当前对象(也就是this)同步整个方法。只要在该方法在声明的时候加上synchronized修饰符就行

当然如果期望将所有方法都添加上synchronized修饰符就能解决同步问题,但是这样其实会带来更多的问题:
1. 它使得JVM性能下降严重
2. 大大增加了死锁的可能性
3. 并不总是需要对对象同步,如果仅仅只是保证了该对象所属的类对象同步,可能无法保护需要包含的资源

3.2 同步的替代方法

同步也会带来很多问题,因此这有几种替代同步的方法,在考虑使用同步之前请先考虑这些方法:
1. 尽可能使用局部变量,而不是使用字段。局部变量不存在同步问题
2. 基本类型在java中是安值传递的,因此不存在任何字段交互的,自然也就是线程安全的。例如Math.sqrt()。如果是对象的引用是没有办法阻止其他线程访问操作的。但是需要注意的是String等不可变的类型是安全的,因为他们从创建时起就没有改变。但是StringBuffer是不安全的
3. 构造函数中一般是不不需要考虑线程安全的因为还没有生成对象的引用,但是有也有一些不常见的例外。比如说构造函数依赖于另一个线程的另一个对象,但是这个对象可能会在构造函数运行的过程中变化。或者构造函数将正在创建的对象引用传递给其他线程中。
4. 使用不可变的对象比如使用private final字段的对象,此外还要注意不用编写任何可能改变它们的方法。
5. 将非线程安全的类作为线程安全类的私有对象,并且不用泄漏非线程安全对象的引用,这样就能以线程安全的方式访问。
6. 可以使用线程安全但可变的类,比如说java.util.concurrent.atomic包中的类,如AtomicInteger,或者AtomicReference(需要说明的是这里的线程安全指的是获取变量引用和设计线程是安全的,但是并不代表变量是线程安全的)
7. 对于集合和映射,应该使用Collections中的方法把它们包装在一个线程安全的版本中。例如是foo,可以用Collection,synchronizedSet(foo)得到这个集合线程安全的视图。

3.3死锁

防止死锁最重要的是要避免不必要的同步。或者采用其他替代同步的方法。
如果多个线程需要独占访问同样的一个资源集,而每个线程分别有这些资源不同的子集的锁则会发生死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值