java并发(Concurrency)《三 Synchronization关键字》 ---来源于oracle官网

Synchronization关键词的作用和缺陷

Threads communicate primarily by sharing access to fields and the objects reference fields refer to. This form of communication is extremely efficient, but makes two kinds of errors possible: thread interference and memory consistency errors. The tool needed to prevent these errors is synchronization.
However, synchronization can introduce thread contention, which occurs when two or more threads try to access the same resource simultaneously and cause the Java runtime to execute one or more threads more slowly, or even suspend their execution

线程通信主要通过共享访问字段和对象,这种形式的交流非常有效,但是可能会引起两种错误:线程干扰和内存一致错误。synchronization可以解决这两种错误。
然而,synchronization也会引起线程争抢,当两个甚至多个线程试图在同一时间去争抢同一资源的时候会引起程序执行缓慢,甚至中断程序运行。

线程干扰(thread interference)

定义一个简单的class Counter

class Counter {
    private int c = 0;
    public void increment() {
        c++;
    }
    public void decrement() {
        c--;
    }
    public int value() {
        return c;
    }
}

increment会让 c+1,decrement会让c-1,但是在多线程的情况下,可能会产生非我们期望的效果(c+1和c-1同时进行等)。在不同的线程中运行两个操作(increment + decrement),由于交错的作用于相同的数据。这会导致两个操作包括多个步骤,步骤的序列重叠,因此结果无法预测。
无须赘述,直接引用官网的demo说明

It might not seem possible for operations on instances of Counter to interleave, since both operations on c are single, simple statements. However, even simple statements can translate to multiple steps by the virtual machine. We won’t examine the specific steps the virtual machine takes — it is enough to know that the single expression c++ can be decomposed into three steps:
Retrieve the current value of c.
Increment the retrieved value by 1.
Store the incremented value back in c.
The expression c-- can be decomposed the same way, except that the second step decrements instead of increments.

Suppose Thread A invokes increment at about the same time Thread B invokes decrement. If the initial value of c is 0, their interleaved actions might follow this sequence:
Thread A: Retrieve c.
Thread B: Retrieve c.
Thread A: Increment retrieved value; result is 1.
Thread B: Decrement retrieved value; result is -1.
Thread A: Store result in c; c is now 1.
Thread B: Store result in c; c is now -1.
Thread A’s result is lost, overwritten by Thread B. This particular interleaving is only one possibility. Under different circumstances it might be Thread B’s result that gets lost, or there could be no error at all. Because they are unpredictable, thread interference bugs can be difficult to detect and fix.

大致是说 c++过程分3步

  1. 获取c
  2. c ++
  3. 将 新的c保存

线程A,B在同一时间操作c,假设初始c == 0
A操作c+1 === 1 B操作c -1 === -1 。最后保存c,可能A的操作就会被覆盖,即A操作的数据丢失,反之B操作的数据丢失。这种结果是不可预知的(unpredictable)

内存一致错误(Memory Consistency Errors)

int counter = 0;
count++;
如果这两条语句在一个线程当中执行,那么结果是期待的 1;
但是假设这两条语句在不同的线程当中执行,那么结果还是 0。没法保证A线程的操作能够及时通知到B线程。(there’s no guarantee that thread A’s change to counter will be visible to thread B — unless the programmer has established a happens-before relationship between these two statements.)
create happens-before relationships(假设t是一个线程实例)

  1. t.start()
  2. t.join()

使用Synchronized关键词的两种形式

Synchronized Methods
public class SynchronizedCounter {
    private int c = 0;
    public synchronized void increment() {
        c++;
    }
    public synchronized void decrement() {
        c--;
    }
    public synchronized int value() {
        return c;
    }
}

如果count是SynchronizedCounter的一个实例,那么定义的这些同步方法有两个做用:

  1. 首先,它不可能对同一对象的两个同步方法调用交错。当一个线程正在执行一个同步的对象方法的时候,其他调用该方法的线程会暂停执行,直到当前线程执行完成
  2. 当同步方法退出时,会为当前对象的后续调用产生happens-before relationships,以确保所有的线程都能被通知到。

这种方式也会产生liveness的问题(后续会提到)

Synchronized Statements

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}
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++;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值