使用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)的更多相关文章

  1. Java并发编程:线程的同步

    Java并发编程:线程的同步 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...

  2. Java并发编程的4个同步辅助类

    Java并发编程的4个同步辅助类(CountDownLatch.CyclicBarrier.Semphore.Phaser) @https://www.cnblogs.com/lizhangyong/ ...

  3. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semphore、Phaser)

    我在<jdk1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  4. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semaphore、Phaser)

    我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  5. Java并发编程(六)-- 同步块

    上一节已经讲到,使用Synchronzied代码块可以解决共享对象的竞争问题,其实还有其他的方法也可以避免资源竞争问题,我统称他们为Java同步块.Java 同步块(synchronized bloc ...

  6. Java并发编程实例(synchronized)

    此处用一个小程序来说明一下,逻辑是一个计数器(int i):主要的逻辑功能是,如果同步监视了资源i,则不输出i的值,但如果没有添加关键字synchronized,因为是两个线程并发执行,所以会输出i的 ...

  7. Java并发编程知识点总结Volatile、Synchronized、Lock实现原理

    Volatile关键字及其实现原理 在多线程并发编程中,Volatile可以理解为轻量级的Synchronized,用volatile关键字声明的变量,叫做共享变量,其保证了变量的“可见性”以及“有序 ...

  8. 【Java并发编程之深入理解】Synchronized的使用

    原文:https://blog.csdn.net/zjy15203167987/article/details/82531772 1.为什么要使用synchronized 在并发编程中存在线程安全问题 ...

  9. 转:【Java并发编程】之七:使用synchronized获取互斥锁的几点说明

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17199201     在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访 ...

  10. 【Java并发编程】之七:使用synchronized获取互斥锁的几点说明

    在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确 ...

随机推荐

  1. [转帖]SQL SERVER中隐式转换的一些细节浅析

    https://www.cnblogs.com/kerrycode/p/5853257.html 其实这是一篇没有技术含量的文章,精通SQL优化的请绕道.这个缘起于在优化一个SQL过程中,同事问了我一 ...

  2. [转帖]Prometheus-使用python开发exporter

    exporter有很多,但想要特定需求的话,还需自行开发.在这里使用python写一个exporter,用于监控/root下的目录数量. 开发exporter需要使用prometheus_client ...

  3. [转帖]Oracle-UNDO篇

      原文地址:https://www.modb.pro/db/70802?xzs= 一:请描述什么是Oracle Undo. 二:请描述UNDO的作用. 三:请谈谈你对Manual Undo Mana ...

  4. 人工智能GPT科普知识的简单总结

    人工智能GPT相关知识的简单总结 背景 工作已经很久, 工作十几年来有过好多波新的技术浪潮. 但是每次都离技术前沿比较远. 最近发现只低头拉车是一个没有前途的行为. 人生很短, 选择很重要, 不仅要低 ...

  5. 【转帖】text-davinci-003和ChatGPT之间的不同点

    https://zhuanlan.zhihu.com/p/603709081 先看下GPT的发展时间线 InstructGPT(2022 年 1 月)是一系列 GPT-3 模型(包括 text-dav ...

  6. ABP 领域服务层学习记录

    在ABP框架中有一个约定,所有的领域服务都应该继承并实现IDomainService接口,在领域层Core创建某一个实体的领域服务类,继承并实现IDomainService接口.在ABP框架中,领域服 ...

  7. C++ CryptoPP使用AES加解密

    Crypto++ (CryptoPP) 是一个用于密码学和加密的 C++ 库.它是一个开源项目,提供了大量的密码学算法和功能,包括对称加密.非对称加密.哈希函数.消息认证码 (MAC).数字签名等.C ...

  8. 1.1 Windows驱动开发:配置驱动开发环境

    在进行驱动开发之前,您需要先安装适当的开发环境和工具.首先,您需要安装Windows驱动开发工具包(WDK),这是一组驱动开发所需的工具.库.示例和文档.然后,您需要安装Visual Studio开发 ...

  9. CSS文本,字体设置与元素边框,阴影,显示模式

    什么是元素的显示模式 网页中的标签很多,在不同的地方使用不同类型的标签. 元素显示模式就是标签以什么方式进行显示.如:div自己占一行,span一行可以放多个. HTML元素一般分为块元素和行内元素两 ...

  10. 【OpenCV】基于cv2的图像阈值化处理【超详细的注释和解释】掌握基本操作

    说在前面的话 博主今天给大家带来人工智能的一个重要领域的入门操作,opencv包的使用和基本操作,希望大家可以从中学到一些东西! 前言 那么这里博主先安利一下一些干货满满的专栏啦! 手撕数据结构htt ...