14.synchronized关键字
作者:互联网
synchronized关键字
导言
本节将介绍多线程中一个比较重要的知识点synchronized的关键字。什么是synchronized的?synchronized的中文叫做同步,
它是一个关键字,可用来给对象和方法或者代码块加锁。当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码,
简而言之就是被synchronized修饰的代码,同一时刻最多只有一个线程执行这段代码。
那么 synchronized可以修饰哪些代码呢?
第一个是代码块
被synchronized修饰的代码块称之为同步代码块,
小括号中的object是同步锁,也叫同步对象,它可以是任意对象,包括this。
第二个是方法被synchronized修饰的方法称之为同步方法。
第三个是静态方法,被synchronized修饰的静态方法称之为静态同步方法,
无论是同步代码块还是同步方法或者是静态同步方法,它们的作用都是一样的。那就是写在大括号里面的代码同一时刻最多只有一个线程执行这段代码,
下面我们来通过一个例子来感受一下同步的好处。首先自定义一个卖票的任务,在任务中定义一个int类型的quantity属性表示这个数量。接着在run方法中判断车票数量是否大于0,当车票数量大于0时出售车票,别忘了还将车票数量减一。
接下来执行这个卖票任务,首先将卖票任务创建出来,然后创建出三个线程。接着将卖票任务分别传递给这三个线程,最后启动这三个线程。
从运行结果来看,程序出现了bug,卖出了三张10号车票,
下面我们将使用同步代码块来解决这个问题,改写之前的卖票任务,将卖票代码放入同步代码块中,这里需要注意的是我们需要区分哪些内容应该放入同步代码块中,哪些内容不应该放入同步代码块中。例如我们不应该将整个while循环放入同步代码块中,因为这样意味着一个线程就可以卖完所有车票,就失去了多线程的意义,所以不要将整个while循环放入同步代码块中,
我们可以把打印车票和减少车票数量的代码放入同步代码块中,这是改写后的售票任务代码。
从运行结果来看,解决了重复车票的问题,
但是出现了新问题,有两张错票,0号票和-1号票,
我们明明都用了同步,他们又是怎么出现的?问题就处在同步代码块内部程序运行至while循环值当quantity等于1,也就是车票数量为一,三个线程同时判断quantity是否大于0时,此时条件成立,
于是三个线程顺利进入while循环体,接下来碰到同步代码块,
他们三个开始争夺同步锁,拿到手的线程进入同步代码块内部执行卖票代码,没有拿到锁的线程继续等待,但三个线程终究都会拿到手,所以卖票代码被执行了三遍,
quantity被递减了三次,于是就产生了0-1的情况,问题竟然已经找到,下面我们来解决它改写之前的任务demo,在同步代码块中再判断一遍quantity是否大于0,形成同步代码块内外双重判断。
从运行结果来看,错票问题得到解决。
下面我们用同步方法再来改写一次任务代码,将同步代码块抽取出来,封装成一个同步方法。就像这样,
下面我们来运行程序试试,从运行结果来看依然是没有问题的。
最后我们来总结一下本节的内容。本节我们介绍了synchronized关键字,它可以用来给对象和方法或者大模块加锁。当他锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码,在实际开发中经常会用到同步。
附录:
笔记完整文本:
本节将介绍多线程中一个比较重要的知识点summarize的关键字。什么是realize的?So realize的中文叫做同步,它是一个关键字,可用来给对象和方法或者代码块枷锁。当它锁定一个方法或者一个大模块的时候,同一时刻最多只有一个线程执行这段代码,简而言之就是被servlet子修饰的代码,同一时刻最多只有一个线程执行这段代码。那么 so let's可以消失哪些代码呢?第一个是代码块被so eyes销售的代码块称之为同步代码块,小括号中的object是同步锁,也叫同步对象,它可以是任意对象,包括this。 第二个是方法被servlet的修饰的方法称之为同步方法。第三个是静态方法,被so赖销售的静态方法称之为静态同步方法,无论是同步代码块还是同步方法或者是静态同步方法,它们的作用都是一样的。那就是写在大括号里面的代码同一时刻最多只有一个线程执行这段代码,下面我们来通过一个例子来感受一下同步的好处。首先自定义一个卖票的任务,在任务中定义一个int类型的quantity属性表示这个数量。接着在run方法中判断车票数量收获大于0,当车票数量大于0时出售车票,别忘了还将车票数量减一。 接下来执行这个卖票任务,首先将卖票人物创建出来,然后创建出三个线程。接着将卖票任务分别传递给这三个线程,最后启动这三个线程。从运行结果来看,程序出现了bug,卖出了三张10号车票,下面我们将使用同步大模块来解决这个问题,改写之前的卖票任务,将卖票代码放入同步代码块中,这里需要注意的是我们需要区分哪些内容应该放入同步代码宽容,哪些内容不应该放入同步代码块中。例如我们不应该将整个via循环放入同步代码块中,因为这样意味着一个县城就可以卖完所有车票,就失去了多线程的意义,所以不要将整个where循环放入同步带模块中,我们可以把打印车票和减少车票数量的代码放入同步代码块中,这是改写后的售票任务代码。 从运行结果来看,解决了重复车票的问题,但是出现了新问题,有两张错票,0号票和-1号票,我们明明都用了同步,他们又是怎么出现的?问题就处在同步大板块内部程序运行至v2循环值当quantity等于1,也就是车票数量为一,三个线程同时判断宽特点是否大于0时,此时条件成立,于是三个线程顺利进入VR循环体,接下来碰到同步大板块,他们三个开始争夺同步所拿到手的线程进入同步代码块内部执行卖票代码,没有拿到锁的线程继续等待,但三个线程终究都会拿到手,所以卖票代码被执行了三遍,quantity被地点了三次,于是就产生了0-1的情况,问题竟然已经找到,下面我们来解决它改写之前的任务demo,在同步代码块中再判断一遍quantity是否大于0,形成同步大板块内外双重判断。 从运行结果来看,错票问题得到解决。下面我们用同步方法再来改写一次任务代码,将同步代码块抽取出来,封装成一个同步方法。就像这样,下面我们来运行程序实施,从运行结构来看依然是没有问题的。最后我们来总结一下本节的内容。本节我们介绍了solar的关键字,它可以用来给对象和方法或者大模块枷锁。当他锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码,在实际开发中经常会用到同步。
标签:同步,14,synchronized,卖票,代码,关键字,线程,车票 来源: https://www.cnblogs.com/cj8357475/p/16086028.html