Java并发编程实例--13.方法同步(synchronized)
使用synchronized关键字去控制对某个方法的并发调用。
某一时段内,只能有一个线程可以读取该方法。
其他线程需要等待前面线程调用完毕后方可调用。
不过,静态方法有着不同的行为。
虽然也是每次只能有一个线程调用它,但是另一个线程可以调用该类对象的其他非静态方法。
这一点需要注意,因为如果2个线程可读取2个不同的同步方法,一个是静态另一个不是。
如果这2个方法修改的是同样的数据,可能会导致数据不一致错误。
本例中,我们将有一个银行账户和2个线程;1个线程存钱,1个线程取钱。这种情况,如果不适用方法同步机制账户里的钱就不对了。方法同步机制保证了账户的最终平衡。
Account.java
package com.dylan.thread.ch2.c01.task;
/**
* This class simulates a bank account
*
*/
public class Account {
/**
* Balance of the bank account
*/
private double balance;
/**
* Returns the balance of the account
* @return the balance of the account
*/
public double getBalance() {
return balance;
}
/**
* Establish the balance of the account
* @param balance the new balance of the account
*/
public void setBalance(double balance) {
this.balance = balance;
}
/**
* Add an import to the balance of the account
* @param amount the import to add to the balance of the account
*/
public synchronized void addAmount(double amount) {
double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp+=amount;
balance=tmp;
}
/**
* Subtract an import to the balance of the account
* @param amount the import to subtract to the balance of the account
*/
public synchronized void subtractAmount(double amount) {
double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp-=amount;
balance=tmp;
}
}
Company.java
package com.dylan.thread.ch2.c01.task;
/**
* This class simulates a company that pays a salary an
* insert money into an account
*
*/
public class Company implements Runnable {
/**
* The account affected by the operations
*/
private Account account;
/**
* Constructor of the class. Initializes the account
* @param account the account affected by the operations
*/
public Company(Account account) {
this.account=account;
}
/**
* Core method of the Runnable
*/
public void run() {
for (int i=0; i<100; i++){
account.addAmount(1000);
}
}
}
Bank.java
package com.dylan.thread.ch2.c01.task;
/**
* This class simulates a bank or a cash dispenser that takes money
* from an account
*
*/
public class Bank implements Runnable {
/**
* The account affected by the operations
*/
private Account account;
/**
* Constructor of the class. Initializes the account
* @param account The account affected by the operations
*/
public Bank(Account account) {
this.account=account;
}
/**
* Core method of the Runnable
*/
public void run() {
for (int i=0; i<100; i++){
account.subtractAmount(1000);
}
}
}
Main.java
package com.dylan.thread.ch2.c01.core;
import com.dylan.thread.ch2.c01.task.Account;
import com.dylan.thread.ch2.c01.task.Bank;
import com.dylan.thread.ch2.c01.task.Company;
/**
* Main class of the example. It creates an account, a company and a bank
* to work with the account. The final balance is equal to the initial.
*
*/
public class Main {
/**
* Main method of the example
* @param args
*/
public static void main(String[] args) {
// Creates a new account ...
Account account=new Account();
// an initialize its balance to 1000
account.setBalance(1000);
// Creates a new Company and a Thread to run its task
Company company=new Company(account);
Thread companyThread=new Thread(company);
// Creates a new Bank and a Thread to run its task
Bank bank=new Bank(account);
Thread bankThread=new Thread(bank);
// Prints the initial balance
System.out.printf("Account : Initial Balance: %f\n",account.getBalance());
// Starts the Threads
companyThread.start();
bankThread.start();
try {
// Wait for the finalization of the Threads
companyThread.join();
bankThread.join();
// Print the final balance
System.out.printf("Account : Final Balance: %f\n",account.getBalance());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
Account : Initial Balance: 1000.000000
deposit 1000, balance:2000.0
deposit 1000, balance:3000.0
withdraw 1000, balance:2000.0
withdraw 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
withdraw 1000, balance:0.0
deposit 1000, balance:1000.0
Account : Final Balance: 1000.000000
Java并发编程实例--13.方法同步(synchronized)的更多相关文章
- Java并发编程:线程的同步
Java并发编程:线程的同步 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...
- Java并发编程的4个同步辅助类
Java并发编程的4个同步辅助类(CountDownLatch.CyclicBarrier.Semphore.Phaser) @https://www.cnblogs.com/lizhangyong/ ...
- Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semphore、Phaser)
我在<jdk1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...
- Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semaphore、Phaser)
我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...
- Java并发编程(六)-- 同步块
上一节已经讲到,使用Synchronzied代码块可以解决共享对象的竞争问题,其实还有其他的方法也可以避免资源竞争问题,我统称他们为Java同步块.Java 同步块(synchronized bloc ...
- Java并发编程实例(synchronized)
此处用一个小程序来说明一下,逻辑是一个计数器(int i):主要的逻辑功能是,如果同步监视了资源i,则不输出i的值,但如果没有添加关键字synchronized,因为是两个线程并发执行,所以会输出i的 ...
- Java并发编程知识点总结Volatile、Synchronized、Lock实现原理
Volatile关键字及其实现原理 在多线程并发编程中,Volatile可以理解为轻量级的Synchronized,用volatile关键字声明的变量,叫做共享变量,其保证了变量的“可见性”以及“有序 ...
- 【Java并发编程之深入理解】Synchronized的使用
原文:https://blog.csdn.net/zjy15203167987/article/details/82531772 1.为什么要使用synchronized 在并发编程中存在线程安全问题 ...
- 转:【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17199201 在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访 ...
- 【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确 ...
随机推荐
- [转帖]Shell 判断文件或文件夹是否存在(不存在则创建)
目录 1. 文件夹不存在创建文件夹 2. 判断文件夹是否存在 3. 判断文件是否存在 4. 常用的文件比较符 1. 文件夹不存在创建文件夹 if [ ! -d "/data/" ] ...
- 【转帖】MySQL索引
数据表如何用索引快速查找 索引是 排好序的快速查找的数据结构 索引存储在文件系统中 索引的文件存储形式与存储引擎有关 索引数据结构:可以是二叉树.红黑树.Hash表.B-Tree.B+Tree 1.二 ...
- [转帖]Tail Latency学习
https://www.cnblogs.com/Rohn/p/15123758.html Latency,中文译作延迟,Tail Latency即尾延迟. 实际生产中的Latency是一种(概率)分布 ...
- NOI Linux 下 Geany 配置教程
没有括号补全? 现在有自动括号补全了! 红色的 a.cpp 的意思是 a.cpp 没有保存. 现在来设置编译运行的快捷键. 不难推测 "%e" 是可执行文件的意思,"%f ...
- 【调研】VictoriaMetrics的上报api能否替换prometheus的api?
prometheus的上报api在:https://github.com/prometheus/client_golang VictoriasMetrics的上报API在:https://github ...
- MySQL 知识点总结(简易版)
MySQL 总结(简易版) 基本语法 0. 1基本语法 # 登录MySQL $ mysql -u root -p12345612 # 退出MySQL数据库服务器 exit; -- 显示所有数据库 sh ...
- 基于密码学的身份混淆系统 -- idmix
简介 Hyperledger Fabric的Idemix是一个基于密码学的身份混淆系统,它提供了一种在区块链网络中实现用户隐私的方法.Idemix的主要特性是它的零知识证明系统,这是一种允许用户证明他 ...
- vue 动态路由刷新页面404
1.如果你的静态路由最后有如下代码: // 404 page must be placed at the end !!! { path: "*", redirect: " ...
- 强化学习基础篇[2]:SARSA、Q-learning算法简介、应用举例、优缺点分析
强化学习基础篇[2]:SARSA.Q-learning算法简介.应用举例.优缺点分析 1.SARSA SARSA(State-Action-Reward-State-Action)是一个学习马尔可夫决 ...
- Libevent [补档-2023-08-29]
libevent的使用 8-1 安装 自己百度一下,安装它不是特别难,加油!!! 8-2 libevent介绍 它是一个开源库,用于处理网络和定时器等等事件.它提供了跨平台的API,能够在不同 ...