时间:2021-05-19
java多线程的同步方法实例代码
先看一个段有关银行存钱的代码:
class Bank { private int sum; public void add(int num){ sum = sum + num; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("total num is : " + sum); }}class Custom implements Runnable{ private Bank b = new Bank(); @Override public void run() { for(int i = 3 ; i > 0 ; i--) b.add(100); }}public class BankDemo{ public static void main(String[] args) { Custom custom = new Custom(); Thread t1 = new Thread(custom); Thread t2 = new Thread(custom); t1.start(); t2.start(); }}此代码的运行结果为:
total num is : 100total num is : 300total num is : 400total num is : 500total num is : 500total num is : 600可以看出sum的值与预期的效果不太一样;造成这种现象的原因有两个:
1.程序存在两个以上的子线程;
2.子线程中存在多条语句操作同一变量;
上述例子中:创建了两个子线程·t1 和 t2,分别向银行中存钱。但是可以看出银行的实力随着Custom的创建,只创建了一个对象。也就是说我们只操作一个数据变量即为银行中钱的总数sum;当两个子线程开启的时候run方法中调用了bank的add方法,而add方法中有两个语句都在操作sum一个sum的增加,一个是打印sum,当两个子线程抢占cpu执行各自的程序的时候会出现:
当t1执行到add以后,t2抢到了cpu的执行权,执行也是执行了add语句,随后打印出sum的值,这时候由于sum增加了两次,所以打印出来的sum值为200。类推,假如这个时候t1又抢回了cpu的执行权,因此又打印出一次200。
显然这种现象是我们不希望产生的。我们希望一个线程存完钱然后打印出结果,之后才允许下一次添加操作。这就是多线程会产生的问题,线程不安全。
我们应尽量避免这种现象的发生,Java给我们提供了三种方法来解决这个问题:
第一种:同步代码块
//private Object obj = new Object(); public void add(int num) { synchronized (this) { sum = sum + num; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("total num is : " + sum); } }将多线程中需要操作同一数据对象的语句使用同步代码块包含。同步代码块的原理就是:
1.java中每个对象都有一个内置锁;
2.当程序运行到同步代码块的时候首先会获取指定对象的锁,这个锁对于多个线程来说是唯一的。我们可以创建任意一个对象(obj)让他当作同步代码块的锁。
3.当程序中只有一个只有一个锁的话我们还可以使用this,this代表当前执行代码所操作的实例对象的锁。即拥有add方法的类的对象,即bank。
4.两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
这样就可以操作同一个数据的多条语句只能在“同一段时间”只能被一个子线程所操作。
第二种 同步函数
public synchronized void add(int num) { sum = sum + num; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("total num is : " + sum); }除了同步代码块以外我们还可以将需要同步的操作抽象成一个函数,然后将这个函数用synchronized修饰,形成同步方法。比如上述例子中的add方法中的语句都在操作sum对象。我们就可以将add方法使用synchronized修饰。这样也能达到代码同步的效果。
同步方法使用的锁其实就是 this。
值得一提的是:同步方法和同步代码块,在开发程序的时候我们更推荐使用同步代码块。
1.同步代码块可以绑定任意对象,而同步函数只能绑定该类对象this
2.如果多个线程使用同一个锁的话,那么两者均可以使用,如果存在多个锁的(比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁),只能使用同步代码块。
静态方法的同步
同步方法
同步代码块:
public synchronized void add(int num){ synchronized (Bank.Class) { }}静态方法的默认同步锁是当前方法所在类的.class 对象,注意this与static不可以连用,所以不能使用this.Class
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
java多线程-同步块Java同步块(synchronizedblock)用来标记方法或者代码块是同步的。Java同步块用来避免竞争。本文介绍以下内容:Java
Java中CountDownLatch进行多线程同步详解CountDownLatch介绍在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法:1
0.关于线程同步(1)为什么需要同步多线程?线程的同步是指让多个运行的线程在一起良好地协作,达到让多线程按要求合理地占用释放资源。我们采用Java中的同步代码块
java多线程的几种实现方法总结1.多线程有几种实现方法?同步有几种实现方法?多线程有两种实现方法,分别是继承Thread类与实现Runnabl
本博客简介介绍一下java线程的join方法,join方法是实现线程同步,可以将原本并行执行的多线程方法变成串行执行的如图所示代码,是并行执行的publiccl