1.取款问题
比如你在银行里存了1000块,从银行柜台取出600,同时也在取款机取出600,正常的话第二次在取款机取款由于存款少于600所以取不出来,我们实践一下:
银行账户类
public class BankAccount { int money=1000; public int getMoney(int num) { if ( money<num) { return -1; } else { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } money -= num; System.out.println("剩了"+money); return money; } } }
线程类
class ThreadBank extends Thread { BankAccount myAccount; ThreadBank(BankAccount myAccount) { this.myAccount = myAccount; } @Override public void run() { if(myAccount.getMoney(600)!=-1){ System.out.println("取款成功"); }else{ System.out.println("余额不足,不能取款"); } } }
测试类
public static void main(String[] args) { BankAccount myAccount= new BankAccount(); ThreadBank thread1=new ThreadBank(myAccount); ThreadBank thread2=new ThreadBank(myAccount); thread1.start(); thread2.start();}
结果
剩了400 取款成功 剩了-200 取款成功
从程序结果可以看出两次取钱都成功了,这就是线程同步导致的问题。
2.解决取款同步问题
利用sychronized关键字解决同步问题,Synchronized关键字:
当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。
Java中的每个对象都有一把锁(lock)或者监视器。当访问某个对象的synchronized方法时,表示将该对象上锁,此时其他任何线程都无法再访问该synchronied方法了,直到之前的那个线程执行方法完毕后(或者抛出了异常),那么将该对象的锁释放掉,其他线程才有可能再去访问该synchronized方法
注意:如果一个对象有多个synchronized方法,某一时刻某个线程已经进入到某个synchronized方法,那么在该方法没有执行完毕前,其他线程是无法访问该对象的任何synchronized方法的。
1)在getMoney方法前面加入synchronized加入关键字
public class BankAccount { int money=1000; public synchronized int getMoney(int num) { if ( money<num) { return -1; } else { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } money -= num; System.out.println("剩了"+money); return money; } } }
2) static synchronized方法
如果某个synchronized方法是static的,那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是synchronized方法所在的对象所对应的Class对象,因为Java中无论一个类有多少个对象,这些对象会对应唯一一个Class对象,因此当线程分别访问同一个类的两个对象的两个static,synchronized方法时,他们的执行顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始执行
静态synchronized方法
class Bank { public static synchronized void getMoney() { for (int i = 0; i < 10; i++) { System.out.println("===== " + i); } }
线程类
class ThreadStatic extends Thread { Bank bank; ThreadStatic(Bank bank) { this.bank = bank; } @Override public void run() { bank.getMoney(); } }
测试类
public static void main(String[] args) { Bank bank1 = new Bank(); Bank bank2 = new Bank(); ThreadStatic thread1 = new ThreadStatic(bank1); ThreadStatic thread2 = new ThreadStatic(bank2); thread1.start(); thread2.start(); }
结果
===== 0 ===== 1 ===== 2 ===== 3 ===== 4 ===== 5 ===== 6 ===== 7 ===== 8 ===== 9 ===== 0 ===== 1 ===== 2 ===== 3 ===== 4 ===== 5 ===== 6 ===== 7 ===== 8 ===== 9
把static去掉,大家可以实践一下
3)Synchronized块写法
Synchronized(object){}表示线程执行的时候对object上锁
class ThreadStatic extends Thread { Bank bank; ThreadStatic(Bank bank) { this.bank = bank; } @Override public void run() { bank.getMoney(); } }
This表示对本对象加锁
public static void main(String[] args) { Bank bank1 = new Bank(); ThreadStatic thread1 = new ThreadStatic(bank1); ThreadStatic thread2 = new ThreadStatic(bank1); thread1.start(); thread2.start(); }
两个线程调用同一个对象的方法,那么输出结果是什么呢,大家打印出来看一下,如果你没有写错的话,打印出来的结果肯定是按顺序执行的。
Synchronized方法和方法块写法区别:
Synchonized方法是一种粗粒度的并发控制,在某一时刻只能有一个线程执行该synchronized方法,synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的代码是可以被多个线程同时访问到的
相关推荐
银行账户的存取款线程设计银行账户的存取款线程设计
Java提供了`synchronized`关键字来实现线程同步,它可以确保同一时间只有一个线程可以访问特定的代码块或方法。在存款和取款方法中,可能会使用`synchronized`关键字来确保线程安全。 此外,项目可能还使用了`wait...
在IT领域,尤其是在多用户系统或者并发环境中,如银行ATM机系统,正确的同步和线程安全至关重要。...通过合理的线程同步和异步处理,我们可以构建出高效且安全的多线程应用,确保在并发环境下正确地处理事务。
标题中提到的"操作系统实验中的线程同步问题"是指在实验环境下,通过模拟多线程环境来研究和解决线程并发访问共享资源时可能出现的问题。这类问题通常会导致数据混乱、死锁或系统性能下降。解决这些问题的方法包括...
现在,我们来看一个具体的实例——银行账户转账操作,这是一个典型的多线程同步问题。假设我们有如下类: ```java public class Account { private double balance; public synchronized void deposit(double ...
这个问题的标题"张三和太太取款同步问题"暗示了我们正在讨论一个涉及到并发操作的场景,比如银行账户取款,而这个场景可能由两个或多个线程同时执行。这种情况下,如果没有适当的同步机制,可能会出现数据不一致或者...
本文主要介绍了Java 多线程同步问题完整代码,以银行取钱为例,通过代码实例来演示多线程同步问题的解决方案。多线程同步是指在同一程序中有多个顺序流在执行,并且这些顺序流之间需要共享资源或数据。 在操作系统...
在这个银行账户的场景中,我们创建了100个线程,每个线程代表一次独立的存取操作,这有助于提高程序的并行性,但同时也引入了潜在的数据竞争问题。 在描述中提到,代码并未涉及并发和互斥控制。在多线程环境中,当...
综上所述,银行取号模拟系统是一个融合了多线程、VC编程、线程同步、用户交互以及声音处理等多方面技术的综合应用实例。通过这样的系统,开发者可以深入理解多线程在实际问题中的应用,提升软件开发能力。
线程同步就是为了防止这些问题,确保线程按照预定的顺序执行或者在特定条件下等待,以维护数据的一致性和完整性。 在操作系统实验中,我们经常会遇到线程同步的实践问题。通过编写程序,我们可以模拟并发环境,学习...
在Java编程中,银行系统是一个典型的多线程应用案例,因为银行系统中涉及多个并发操作,如存款、取款、转账等,这些操作通常需要在不同的线程中并行执行以提高效率。以下是对"java银行系统多线程"这个主题的详细说明...
Java提供了多种并发控制工具,如synchronized关键字用于实现线程同步,防止数据竞争;Lock接口及其实现类如ReentrantLock提供了更细粒度的锁控制;Semaphore信号量可以控制同时访问特定资源的线程数量;Atomic原子...
Java提供了`synchronized`关键字和`Lock`接口(如`ReentrantLock`)来实现线程同步。例如,在ATM程序中,当一个用户正在取款时,其他用户不能同时访问同一账户,这就需要用到锁机制。 3. **线程通信**:有时线程...
在本案例中,我们关注的是"互斥线程并发",这是一个关键的并发控制概念,确保在任何时候只有一个线程可以访问特定的共享资源,以避免数据竞争和其他并发问题。在"互斥线程并发"中,我们使用同步机制来防止多个线程...
总的来说,Java多线程同步是为了保证并发程序的正确性和一致性,通过`synchronized`关键字和`java.util.concurrent`包提供的工具,开发者可以有效地管理和协调多线程的执行,确保数据的一致性和避免死锁等问题。...
- 多用户访问:如果ATM系统支持多个用户同时操作,需要考虑线程同步和互斥锁,以防止数据竞争。 8. **网络通信**: - 实时通讯:虽然ATM系统通常是离线工作的,但在某些情况下可能需要与银行服务器进行实时通信,...
#### 二、Java线程同步 ##### 2.1 同步的重要性 在多线程环境中,多个线程可能会同时访问共享资源,如果这些线程没有正确地进行同步,则可能会导致数据不一致或者程序行为异常。例如,考虑一个简单的银行账户余额...
在IT行业中,银行存取款程序是金融领域中常见的应用,通常用于自动化处理客户存款、取款、转账等日常银行业务。在这个特定的程序中,我们关注的是它使用Java编程语言构建,并且与管理系统相关。Java是一种广泛使用的...
在Java中,我们可以使用`synchronized`关键字来实现线程同步。在这个实验中,我们定义了一个`sum`类来存储账户余额,`save`类代表存钱操作,`get`类代表取钱操作。 在`save`类的`run`方法中,我们使用`synchronized...