Avatar
0
monkey Enlightened
monkey Enlightened
Volatile boolean khác gì AtomicBoolean
Volatile boolean khác gì so với AtomicBoolean?
  • Answer
java volatile atomicboolean
Remain: 5
5 Answers
Avatar
monkey Enlightened
monkey Enlightened
The Best Answer
  1. Volatile: là một dạng biến thông báo, nghĩa là nó được dùng để các thread thông báo cho nhau rằng biến có sự thay đổi giá trị, tuy nhiên nó không đảm bảo được là giá trị của biến sẽ được đồng bộ

Ví dụ thông báo:

public class VolatileExample {

    private volatile boolean active;

    public void prepare() throws InterruptedException {
        new Thread(() -> {
            System.out.println("application preparing ...");
            sleep(3);
            active = true;
        })
        .start();
    }

    public void start() throws Exception {
        new Thread(() -> {
            while(!active);
            System.out.println("application started");
        })
        .start();
    }

    private static void sleep(int second) {
        try {
            Thread.sleep(second * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        VolatileExample example = new VolatileExample();
        example.prepare();
        example.start();
        sleep(10);
    }
}

Nếu bạn bỏ từ khoá volatile thì hàm System.out.println("application started"); sẽ không bao giờ được in ra

Ví dụ không đảm bảo đồng bộ giá trị:

public class VolatileIntExample {

    private volatile int count;
    private final Map map = new ConcurrentHashMap();

    public void start() {
        Thread[] threads = new Thread[10];
        for (int i = 0 ; i < threads.length ; ++i) {
            threads[i] = new Thread(() ->
                while(count <= 1000000) {
                    ++ count;
                    map.put(Integer.valueOf(count), Integer.valueOf(count));
                }
            });
        }
        for (int i = 0 ; i < threads.length ; ++i) {
            threads[i].start();
        }
    }

    public static void main(String[] args) throws Exception {
        VolatileIntExample example = new VolatileIntExample();
        example.start();
        Thread.sleep(3000);
        System.out.println(example.map.size());
    }
}

nó sẽ in ra ngẫu nhiên, có thể là 979638

  1. AtomicBoolean: vừa có khả năng thông báo vừa đảm bảo giá trị sẽ được đồng bộ, vì bên trong nó sử dụng private volatile int value;, nên trong ví dụ trên, bạn cũng có thể sử dụng thế này:

Ví dụ thông báo:

public class AtomicExample {

    private AtomicBoolean active = new AtomicBoolean(false);

    public void prepare() throws InterruptedException {
        new Thread(() -> {
            System.out.println("application preparing ...");
            sleep(3);
            active.set(true);
        })
        .start();
    }

    public void start() throws Exception {
        new Thread(() -> {
            while(!active.get());
            System.out.println("application started");
        })
        .start();
    }

    private static void sleep(int second) {
        try {
            Thread.sleep(second * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        AtomicExample example = new AtomicExample();
        example.prepare();
        example.start();
        sleep(10);
    }
}

Ví dụ đông bộ dữ liệu:

public class AtomicIntExample {

    private AtomicInteger count = new AtomicInteger(0);
    private final Map map = new ConcurrentHashMap();

    public void start() {
        Thread[] threads = new Thread[10];
        for (int i = 0 ; i < threads.length ; ++i) {
            threads[i] = new Thread(() -> {
                int value;
                while((value = count.incrementAndGet()) <= 1000000) {
                    map.put(Integer.valueOf(value), Integer.valueOf(value));
                }
            });
        }
        for (int i = 0 ; i < threads.length ; ++i) {
            threads[i].start();
        }
    }

    public static void main(String[] args) throws Exception {
        AtomicIntExample example = new AtomicIntExample();
        example.start();
        Thread.sleep(3000);
        System.out.println(example.map.size());
    }
}

nó sẽ in ra 1000000

  • 1
  • Reply
Avatar
Vu Luong Anh Enlightened
Vu Luong Anh Enlightened
Vậy thằng AtomicBoolean có thay thế được volatile boolean trong mọi trường hợp không anh? Hay performance nó bị kém hơn ạ?
  • 0
  • Reply
Avatar
monkey Enlightened
monkey Enlightened
Nó có thể thay thế trong mọi trường hợp em ạ, tuy nhiên là nó sẽ tốn memory hơn vì nó là con trỏ, mình không nên lạm dụng, mình dùng đúng ngữ cảnh em ạ
  • 2
  • Reply
Avatar
Vu Luong Anh Enlightened
Vu Luong Anh Enlightened
Vậy em kết luận như này đúng không anh:
  • Dùng volatile boolean khi chỉ có 1 thread write, có thể nhiều threads read
  • Dùng AtomicBoolean khi có nhiều threads write
  • 1
  • Reply
Avatar
monkey Enlightened
monkey Enlightened
  1. Dùng volatile khi em chỉ cần quan tâm đến việc thông báo giữa các thread mà ko quan tâm đến tính chính xác của dữ liệu, ví dụ như trường hợp vòng while loop, em chỉ quan tâm là nếu có thằng nào đó set giá trị active về false là em sẽ break loop và kết thúc, như vậy thì volatile là hợp lý em ạ

  1. Các trường hợp còn lại dùng atomic em ạ

 

 

 

  • 2
  • Reply