synchronized keyword DEMO

本文探讨了并发环境中银行账户的余额操作,通过Bob和Monica的实例展示了线程安全问题,包括账户余额的同步更新与不足金额时的错误处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package HeadFirstJava;

class BankAccount {
    private int balance = 100;
    
    public int getBalance() {
        return balance;
    }
    public void withdraw(int amount) {
        balance = balance - amount;
    }
}

class BobAndMonica implements Runnable {
    private BankAccount account = new BankAccount();

    public static void main(String[] args) {
        BobAndMonica theJob = new BobAndMonica();
        Thread one = new Thread(theJob);
        Thread two = new Thread(theJob);
        one.setName("Bob");
        two.setName("Monica");
        one.start();
        two.start();
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int x = 0; x < 10; x++) {
            makeWithdrawl(10);
        }
        if (account.getBalance() < 0) {
            System.out.println("Overdrawn");
        }
    }
    private synchronized void makeWithdrawl(int amount) {
        if (account.getBalance() >= amount) {
            System.out.println(Thread.currentThread().getName() + " is about to withdraw");
            try {
                System.out.println(Thread.currentThread().getName() + " is going to sleep");
                Thread.sleep(500);
            } catch(InterruptedException ex) {ex.printStackTrace();}
            System.out.println(Thread.currentThread().getName() + " woke up.");
            account.withdraw(amount);
            System.out.println(Thread.currentThread().getName() + " completes the withdrawl");
        } else {
            System.out.println("Sorry, not enough for " + Thread.currentThread().getName());    
        }
    }
    
}

Bob is about to withdraw
Bob is going to sleep
Bob woke up.
Bob completes the withdrawl
Monica is about to withdraw
Monica is going to sleep
Monica woke up.
Monica completes the withdrawl
Bob is about to withdraw
Bob is going to sleep
Bob woke up.
Bob completes the withdrawl
Monica is about to withdraw
Monica is going to sleep
Monica woke up.
Monica completes the withdrawl
Bob is about to withdraw
Bob is going to sleep
Bob woke up.
Bob completes the withdrawl
Monica is about to withdraw
Monica is going to sleep
Monica woke up.
Monica completes the withdrawl
Monica is about to withdraw
Monica is going to sleep
Monica woke up.
Monica completes the withdrawl
Bob is about to withdraw
Bob is going to sleep
Bob woke up.
Bob completes the withdrawl
Monica is about to withdraw
Monica is going to sleep
Monica woke up.
Monica completes the withdrawl
Bob is about to withdraw
Bob is going to sleep
Bob woke up.
Bob completes the withdrawl
Sorry, not enough for Monica
Sorry, not enough for Monica
Sorry, not enough for Monica
Sorry, not enough for Monica
Sorry, not enough for Monica
Sorry, not enough for Bob
Sorry, not enough for Bob
Sorry, not enough for Bob
Sorry, not enough for Bob
Sorry, not enough for Bob
### Java 中 `synchronized` 关键字的作用 在多线程环境中,`synchronized` 是一种用于控制并发访问的关键机制。它通过锁定对象来确保同一时间只有一个线程可以执行被标记为同步的方法或代码块。对于 `demo.list` 的具体用法,可以通过以下方式实现: #### 使用 `synchronized` 方法 如果希望整个方法都被同步保护,则可以直接将方法声明为 `synchronized`。 ```java public class Demo { private List<String> list = new ArrayList<>(); public synchronized void addElement(String element) { list.add(element); } public synchronized String getElement(int index) { return list.get(index); } } ``` 上述代码中,任何调用 `addElement` 或 `getElement` 方法的线程都会获得当前实例 (`this`) 的锁[^1]。 --- #### 使用 `synchronized` 块 当只需要同步部分代码而非整个方法时,可以选择使用 `synchronized` 块。这种方式更加灵活且高效。 ```java public class Demo { private final Object lock = new Object(); private List<String> list = new ArrayList<>(); public void addElement(String element) { synchronized (lock) { // 锁定特定的对象变量 list.add(element); } } public String getElement(int index) { synchronized (lock) { // 同样锁定该对象变量 return list.get(index); } } } ``` 在此示例中,`synchronized` 块仅锁定了一个私有的 `Object` 实例作为监视器,而未锁定整个类实例。这种设计有助于减少不必要的竞争并提高性能。 --- #### 需要注意的问题 尽管 `synchronized` 提供了一种简单的方式来管理线程安全问题,但在实际应用中仍需注意潜在的风险: - **死锁风险**:如果多个线程尝试获取不同的锁顺序不当,可能会导致死锁情况发生。 - **性能开销**:频繁加锁会增加上下文切换的成本,从而影响整体性能。 - **替代方案的选择**:现代 Java 并发库提供了更高效的工具(如 `ReentrantLock`, `ConcurrentHashMap`),可以根据需求考虑这些高级选项代替传统的 `synchronized`。 --- ### 示例场景分析 假设有一个生产者消费者模型,其中涉及对共享列表的操作。以下是基于 `synchronized` 的解决方案: ```java import java.util.ArrayList; import java.util.List; public class ProducerConsumerExample { private static final int MAX_LIMIT = 5; private final List<Integer> sharedList = new ArrayList<>(); public void produce() throws InterruptedException { int value = 0; while (true) { synchronized (sharedList) { while (sharedList.size() == MAX_LIMIT) { System.out.println("Waiting for space..."); sharedList.wait(); // 当队列满时等待 } sharedList.add(value++); System.out.println("Produced: " + (value - 1)); sharedList.notifyAll(); // 唤醒其他可能正在等待的线程 } Thread.sleep(100); // 模拟延迟 } } public void consume() throws InterruptedException { while (true) { synchronized (sharedList) { while (sharedList.isEmpty()) { System.out.println("Nothing to consume, waiting..."); sharedList.wait(); // 如果队列为空则等待 } Integer consumedValue = sharedList.remove(0); System.out.println("Consumed: " + consumedValue); sharedList.notifyAll(); // 唤醒其他可能正在等待的线程 } Thread.sleep(100); // 模拟延迟 } } } // 测试入口 class Main { public static void main(String[] args) { ProducerConsumerExample example = new ProducerConsumerExample(); Thread producerThread = new Thread(() -> { try { example.produce(); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread consumerThread = new Thread(() -> { try { example.consume(); } catch (InterruptedException e) { e.printStackTrace(); } }); producerThread.start(); consumerThread.start(); } } ``` 在这个例子中,`produce()` 和 `consume()` 方法均利用了 `synchronized` 来协调资源的竞争状态,并通过条件判断配合 `wait/notifyAll` 达到动态平衡的效果[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值