java 内部锁和同步机制

sychronized是由一个被称为内部锁或者监控锁的内部组件构成。内部锁在sychronized的两个方面都发挥作用,强制地单独访问一个对象的状态和给每一个sychronized方法建立happen-before关系。

每一个对象都关联着一个内部锁。传统上,每个线程在访问对象时都需要单独和一致的获得一个对象的属性,那么就要在访问这个对象前获得它的内部锁,然后再访问结束后释放它。当线程获得和释放一个内部锁的中间,我们就称为线程持有这个内部锁。当一个线程持有内部锁时,其他的线程就无法访问这个内部锁,试图访问时就会被阻塞。

当一个线程释放内部锁时,一个happen-before关系在这个动作和下一个任意的这个锁的下一个获取动作就会被建立起来。

sychronized语句

另一种创建sychronized编码的方法是使用sychronized语句,不像sychronized方法,sychronized语句必须要指定的对象一定要有内部锁:
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
在这个例子中,addname这个方法会并行的改变lastname和namecount变量,同时也需要防止其他对象的方法调用(调用其他对象的方法可能会造成活跃性问题)没有sychronized语句的话,这里就会被分开。没有sychronized方法,唯一的目的就是调用namelist.add方法。

sychronized语句对于实现细粒度的sychronized化实现并行。假设,举个栗子,类MsLunch 有两个实例字段c1和c2,从来不会一起使用。这两个字段的更新需要同步化,但是也没有任何理由说明c1的更新和c2的更新不能交替执行,而且这样做可以减少并发造成不必要的阻塞。我们创建了两个对象提供锁,而不是利用同步方法或其他关联到此的锁机制。
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();

public void inc1() {
    synchronized(lock1) {
        c1++;
    }
}

public void inc2() {
    synchronized(lock2) {
        c2++;
    }
}

}
使用这种机制需要特别小心,你需要确定在交替更新时不会出错。
重复进入同步
一个线程无法获得另一个线程占用的锁。但一个线程可以获得自己线程占用的锁,这叫做重进入同步。这描述了一种情况同步代码直接或者非直接执行一个也包含Synchronized的代码,并且两个代码集合用相同的锁。除了重复进入同步语句,同步代码必须采取许多措施预防它自己使它自己阻塞

Atomic access
在编码时,一个原子访问就是一次有效的操作事务。原子动作不会在执行到一半时停止,它要么完成,要么不完成。原子操作完成之前你看不到任何的现象。
我们已经看到过增长表达式,比如像,c++,不能被当成是原子操作。即使是一个很简短的表达式,也可以被分解成多个子操作。然而,你可以说这些动作为原子性的:
1.对引用变量和大多数内建变量(除了long和double)的读写操作;
2.对用volatile声明的变量(包括long和double)的读写操作;
原子性操作不会出现交叉,所以使用它们就不用担心线程冲突;然而,这并没有全部消除原子操作也需要sychronized操作,因为还是有可能会出现内存一致性问题。使用volatile变量可以减少内存一致性错误的风险,因为写入volatile变量的方法都会建立一个和后面的读操作的happen-before关系。这表示所有对volatile变量的操作对其他线程都是可见的。更重要的是,当你读取一个volatile的变量时,不仅是可以读取到它最后的一个变化,而且意味着你可以改变它了。
使用简单的volatile变量要比使用sychronized机制同步方便很多,但是也要注意使用时可能会造成内存一致性错误的问题。是否需要做这样的事取决于你应用的大小和复杂的。
java.util.concurrent包里有一些类使用了不依赖sychronized机制的原子操作,我们将在 High Level Concurrency Objects这一节讨论这些问题.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值