您的位置:

并发三大特性:原子性、可见性、有序性

一、原子性

原子性是指一个操作是不可中断的整体,要么全部执行成功,要么全部执行失败。在多线程环境下,原子性是保证数据正确的基础。

Java提供了synchronized关键字和java.util.concurrent.atomic包下的原子类来实现原子操作。

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

在上面的代码中,通过synchronized关键字使increment方法变成原子操作,从而保证了count的正确性。

除此之外,还可以使用AtomicInteger这个原子类来实现计数器:

public class Counter {
    private AtomicInteger count = new AtomicInteger();

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

二、可见性

可见性是指当一个线程修改了共享变量时,另一个线程能够立即看到这个修改。在多线程环境下,可见性是保证数据一致性的基础。

Java提供了volatile关键字来实现可见性,它能够保证在读取和修改变量时,都是直接从内存中读取和写入,而不是从缓存中读取和写入。

public class Counter {
    private volatile int count = 0;

    public void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

三、有序性

有序性是指程序执行的顺序与代码的先后顺序一致,Java中的指令重排可能会导致代码执行的顺序不一致,从而产生一系列问题。

Java提供了synchronized和volatile两种方式来保证有序性。

在下面的例子中,线程A和线程B执行的结果可能会不同:

public class OrderExample {
    private int x = 0;
    private boolean flag = false;

    public void write() {
        x = 1;
        flag = true;
    }

    public void read() {
        if (flag) {
            int y = x + 1;
        }
    }
}

在上面的代码中,如果线程A先执行write方法,然后线程B执行read方法,在没有任何同步措施的情况下,y可能为0而不是2。

使用volatile关键字可以避免指令重排:

public class OrderExample {
    private volatile int x = 0;
    private volatile boolean flag = false;

    public void write() {
        x = 1;
        flag = true;
    }

    public void read() {
        if (flag) {
            int y = x + 1;
        }
    }
}

结语

并发编程是一个复杂的问题,掌握并发三大特性对于正确使用多线程至关重要。