JAVA多线程并发(二)-- volatile和synchronized 详解

在Java并发编程中,volatile和synchronized是两个至关重要的关键字,它们帮助开发者解决多线程环境下的可见性、原子性和有序性问题。

一. 简介

1. Volatile

volatile是一个类型修饰符,用来确保对一个变量的读取和写入操作不会被编译器重排序,并且每次读取都直接从主内存中获取最新值,写入时也直接写入主内存,从而保证了多线程环境下的可见性。但需要注意的是,volatile不能保证复合操作(如count++)的原子性

volatile关键字用于确保变量的可见性(visibility)和有序性(ordering),但不保证原子性(atomicity)。

2. Synchronized

synchronized关键字可以用于方法或代码块,它提供了一种锁机制,确保同一时间只有一个线程可以执行特定的代码段,从而达到线程互斥的效果。synchronized不仅保证了可见性,还确保了操作的原子性以及有序性,是更强大的并发控制工具。

二、用法

1. Volatile 的使用

public class VolatileExample {
    private volatile int count = 0;

    public void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

在这个例子中,虽然count使用了volatile,但increment()方法并不是线程安全的,因为count++不是原子操作。然而,getCount()能保证读取到最新的count值。

2 Synchronized 的使用

  1. 方法级别
public class SynchronizedExample {
    private int count = 0;

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

    public synchronized int getCount() {
        return count;
    }
}
  1. 代码块级别
public class SynchronizedBlockExample {
    private int count = 0;
    private Object lock = new Object();

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

    public int getCount() {
        synchronized (lock) {
            return count;
        }
    }
}

三、常用案例实例

  1. Volatile 示例:确保一个标志的可见性
public class VolatileExample {  
    // 使用volatile关键字确保变量的可见性  
    private volatile boolean running = true;  
  
    public void start() {  
        new Thread(() -> {  
            while (running) {  
                // 模拟一些工作  
                System.out.println("Thread is running...");  
                try {  
                    Thread.sleep(1000);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
            System.out.println("Thread is stopping...");  
        }).start();  
    }  
  
    public void stop() {  
        running = false; // 当running被设置为false时,其他线程会立即看到这个改变  
    }  
  
    public static void main(String[] args) {  
        VolatileExample example = new VolatileExample();  
        example.start();  
  
        // 模拟一段时间后停止线程  
        try {  
            Thread.sleep(5000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        example.stop(); // 设置running为false,期望线程停止  
    }  
}
  1. Synchronized 解决并发修改问题

考虑一个经典的银行账户转账问题:

public class BankAccount {
    private double balance;

    public synchronized void deposit(double amount) {
        balance += amount;
    }

    public synchronized void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        } else {
            System.out.println("Insufficient balance.");
        }
    }

    public synchronized double getBalance() {
        return balance;
    }
}

在这个例子中,通过synchronized关键字确保了存取款操作的原子性和一致性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值