00:00
下面呢,咱们就来说一下这个Java是怎么做的,这就回到第四个点了,那么我们说呢,在Java当中。哎,Java中哎说我们我们哎通过这个叫哎同步机制来解决线程的安全问题。好,通过这样的同步机制来解决的,首先呢,咱们说一下最初咱们这个GDK呢,这个在解决线上安全问题的时候呢,提供的两种方式啊,先说一下这个啊最初的两种方式,然后呢,咱们再说一下这个JDT5.0的时候新增的一种方式啊,最初的两种方式呢,一个呢叫同步代码块,哎,另外一个方式二叫同步方法,先来说一下这两种方式,这两种方式呢,咱们先来说一下方式一,哎先来说一下方式一,同步代码块这里边呢,提到了一个关键字,这个关键字呢,叫做snchized的,这个呢,关键字非常难写,差不多呢,是这些关键字里边最难写的一个了。
01:09
Synchronized这个呢,需要大家下来熟悉一下,必须要能够手写出来的,你不能说sin,然后呢,这个提示一下,哎,这个生成是吧,这不行啊,嗯,这呢叫sized,然后呢一对小括号,小括号呢后边一个大括号,哎这样的一个结构,在这个小括号里边呢,需要填一个东西,这个东西呢,咱们叫做同步监视器。然后呢,这个大括号里边,大括号里边呢,就是我们这个单词,你可以翻译成就要同步了啊,大括号里边呢,就是我们需要被同步的代码。嗯,这呢就学完了,通过这样的一个结构呢,咱们去解决所谓的叫线程安全问题,那么这里就涉及到同步天然器啊写谁,然后呢,需要被同步的代码,这个代码应该包谁?就像前面我们讲了个try catch一样啊TRY呢,你有一个大括号,就是包住那些呃,可能会出现异常的代码,那个很好理解了,那现在呢,你这叫需要被同步的代码,在这呢,我们得明确一下,我加一个说明,什么叫需要被同步的代码啊,我们这里边提到说哎,叫操作共享数据的代码,即为啊需要被同步的代码。
02:38
这个大家呢,要理解就是操作共享数据的代码,咱们现在呢,不是说你就希望啊,呃,这个这是一段代码,这段代码呢,咱们希望什么呢?就是这一个线程进来执行,在这里边儿呢,它可能会阻塞。啊,但不管你现在是什么状态,只要你还在这个这个大括号里边,这时候呢,其他的线程呢,都得在这等着,不管你有多少个都得在这等着,当我们这个叫线程一吧,当它出去以后。
03:08
哎,你这几个线程再看看谁能抢到哈,那谁又再进来。这种这个时候呢,咱们才可以保证这是安全的,那么我这个框里边这个代码呢,就是理解为叫需要被同步的代码啊,咱们上面也说到了,就是大家买票这个卖票的话呢,得保证这个其中一个线程操作TK的,别的不能操作了,那这个TK的叫共享数据,那咱们就需要呢把诶操作TK的这些数据啊,就是叫这个了,哎,就是需要我们同步的代码啊,那当然这里边我们其实也是首次呢,来明确说一下,这个叫共享数据啊。哎,这个操作共享数据代码,这里边儿就提到什么是共享数据,那就是多个线程啊,共同操作的,哎,这个变量吧,或者叫数据,哎,这就叫做共享数据。
04:03
这个好理解吧,哎,比如咱们这个本问题当中的这个TK就是。诶,它呢,就是我们的共享数据,那行了,那咱们就需要呢,把这个操作T这个数据呢,给它包起来,那咱们找一找吧,显然呢,是在咱们这个run方法里边了,多个线程来操作的代码都在run里,在run里边我们需要呢,先明确一下共享数据啊,已经知道了是T了,接下来需要把操作7K的代码呢。包起来,那从哪开始包啊,这这这算不算,你是不是判断了一下,这不也在操作这个TK的对吧?这算这这这这也得算是吧,然后你下边这个减点是不是也得算对,但是你要光包衣服,那LC也不行,是不是你LC的包装对那就这一块代码需要拿咱们这个叫诶S,那这块呢就出来提示了,但是你别上来就先用它啊,先去手写一下,去记一下啊,这有个小括号,然后呢,后边有个大括号啊,一直到这个else这个位置来包一下。
05:19
你看咱们这个idea还挺智能的,你这一包它自动它就给你,诶扣移了是吧?嗯,这呢,我们就把它包起来了,这上就是操作共享数据的代码了,嗯,那么这个位置呢,需要写一个东西,这个东西呢,我们叫做同步监视器,好下一个问题同步监视器是什么?哎,这呢叫同步监视器,哎这个同步监视器呢,是一个学名,听着感觉还挺这个吓人的啊监视器了啊那这个呢,我们啊下边写个叫俗称呢啊锁,哎这呢你就很好理解了。
06:01
就像大家咱们刚才说的,你去去厕所的时候呢,怎么就安全了,你进去以后呢,诶锁一下是吧,哎,你一锁这时候就安全了啊,别人呢,他这时候是去开门开不开啊,因为这时候我这个锁给你锁住了啊,所以这个位置呢,我们就呃放一把锁,谁进去的时候呢,谁就拿着这把锁,没进去的这个人呢,就拿不到这个锁,谁能拿到锁谁就操作这个代码啊,那么下个问题,那这个锁啊,或者叫同步监视器放个什么东西呢?我们下一步要说说任何一个类的对象,哎都可以啊,来充当我们这个数。这个范围非常的宽泛,任何一个类的对象都可以充当锁,任何一个对象都可以充当锁,你这写TK的不行啊,这好歹还是一个基本数据类型是吧?不行了,那咱们那整个对象吧,整个对象我在这造一个吧,那那你现成的整一个字符串整一个,是不是有个object也行是吧?哎,我去new一个,比如object,那这呢是随便的一个类的对象了,那我这个obj ctrl c ctrl v往这一扔。
07:14
从语法上来讲就可以了,这就满足了啊。嗯,代码上不报错了,说任何对象都能充当N,我就先扔进来了,那这个就算是写完了。写完了咱们跑一下,刚才呢,不是说有这个线程安全问题吗?咱们把这个他先注意一下,把这个注意一下,咱们再来看一下这个安全问题。你看确实有都能看到这个重票了啊这个啊这呢叫错票,然后接下来我呢,把这个打开,把这个呢打开,现在呢,我们再去执行。
08:01
哎,这时候你看这个重票貌似就没有了。这几个窗口呢,都在抢好结束啦,结束以后的话呢,后边没有错票了,前面呢,你去看一看,其实这个重票呢也没有。没有啊,你要不放心,你再跑几次,这呢我就不跑了,从概率上来讲,此时呢,这个线程安全问题的出现概率就0%,不会出现,这就安全了。嗯,那么此时我们能保证的呢,就是,呃,这个在这段代码当中,我们能保证的就是当你一个线程进来的时候,即使这个线程一在这儿呢,Sleep了,阻塞了,别的线程也得在这等着。直到我们这个县城醒来以后,操作完出去了,别的县城才他们三个,包括人家本身,人家还可以回来再抢啊,哎,你看看这个谁又进去了,那么这里边儿呢?关于这个OB街,咱们再说一说。
09:04
OB接咱们叫做锁或者叫做同步监视器,有没有什么要求呢?这呢也算个要求,这个要求很宽泛,说随便一个对象都行啊,这是没问题的,但是他其实有一个很隐藏的一个要求,这个要求就是要求我们多个线程啊,必须要共用同一把锁。这个锁就一个啊,这个锁就一个啊,这个呃,我再举一个例子啊,举一个咱们生活中的例子,呃,咱就不以说咱们去这个咱们外边这个厕所了,这个不太好说了,咱们说谁呢?说火车上。火车上的话呢,咱们知道一个车厢呢,都会有个厕所了啊,这大家应该都坐过火车了是吧?诶都应该知道,就是你去厕所的时候呢,其实你也不用非得说走到那儿看看这个里边有没有人啊,你就看那个车厢,它那个在这个这个车厢连接处,厕所那块有个灯是吧?对,然后呢,你就这个,你可能是这个座位离的那个厕所比较远,你就看那个灯,那个灯如果是个绿的,哎,就证明里边没有人,哎,你就进去就可以了,然后呢,你要想去厕所,你一看那个灯是红的,哎,就知道里边是有人,哎里边有人呢,言言之义就你不要再冲进去了,对吧,你一冲进去不就先成不安全了嘛,人家正在操作那个是吧?啊,你就不要进去了啊,也就是说那个灯这个车厢的所有人,每个人是一个县城,大家是不是就都看着一个灯就行了啊,那就要求就是咱们咱们所有的这些人啊,所有的县城大家呢,都用同一个锁,这个锁呢,就好比是咱们车厢的那个那个灯一样。
10:49
啊,大家呢,不能什么呢?不能一人一个锁啊,咱们要求呢,得共用一个锁啊,你不能一个人锁,言言之义就是说你不能你自己的座位上有个灯啊,前面一个女生去那个厕所了,他一一进一进去,然后呢,她把她那个位置上的灯从绿的改成红的了,你想去厕所一看,诶,你这是绿的是吧?你是不是又容易误进去啊?
11:12
哎,所以说呢,就是咱们必须所有人都用同一个锁啊,这样的话呢,它才安全,嗯,那么在咱们这个代码当中,我们看一下这个obj对于三个线程来讲是不是唯一的。唯一呗,就是你就看这OBG这个对象到底造了几个呀,对,就一个。啊,咱们在这块是不是就拗过一个window的对象呀,我把这一个对象放到我们这三个线程当中,大家呢,共用同一个window对象,那window对象里边呢,又只有这样一个属性,那大家当然也就共用同一个obj了啊,那大家看啊,我现在把这个代码我往下移,哎哟。那看直接就移到外边了哈,我把它CTRL。
12:00
X,我放到哪,然后放到这儿行不行,这时候线程安全吗?不安全了就啊安全不安全呢?大家是不是就看这个事就行,此时这三个线程是供应的同一个锁吗?不是的,几个锁是不是一个线程一个呀?嗯,你看此时我们再去执行。你看就仍然会出现问题,所以说我们说这个同步难,难在哪呢?就是这里边呢,代码没错,代码你看到说不报错了,不报错不意味着你的代码是对的啊,那你放了一个锁进去了,这个锁呢,达不到要求也不行啊,所以放在这呢是不行的啊,那要我直接在这里边去扭一个呢,这是不是就更不行了。这都不止三个锁了吧,对,你每跑一次的时候,是不是都扭了一个是吧?啊这这就更不行了。
13:06
嗯。好,仍然会有这样的问题,所以这个这个这都是错的,所以咱们呢,得保证它的唯一性,哎,方便呢,就是生命在这个位置上,哎咱们说了任何一个对象呢,都可以充当,就是在这个锁的这个,呃,是哪个类的对象上呢,没有任何要求,但是呢,唯一的要求就是它得要共用同一个。啊,我这是用的object,你也可以呢,随便整一个啊,比如我在最后我class一个狗,咱们自定义的一个类啊dog,然后这个位置呢,你也可以不用这个object,哎,我这呢去dog。有一个dog,然后把我们这个dog呢放到这,哎,这个可以吧。执行。
14:00
那这个咱们设置这个六的时间呢,有点长,所以稍微慢一点啊,没有问题,你再跑几次呢,也是对的啊,所以说呢,大家注意我们这里边说的这个同步加湿器,关于它的这个要求。哎,这个一定要注意,很多时候呢,大家用这种方式去处理限制安全问题了,最后发现不对,还是会有类似的这种重票错票,你一定要去看一下你这个锁是不是同一个,八成这里边锁是用的不是同一个了啊,这个你要小心点,这个问题好正常是咱们关于这个叫同步代码块的一个方式呢,咱们来处理这个现场的安全问题啊,那顺便呢,咱们再说些什么呢,这个咱们使用就写这个死七五啊,咱们使用这个同步。同步的这个方式啊,啊好处呢,就是解决了。解决了啊,这个县城的这个安全问题了,这是一个好事啊,这算是一个好处吧,它有没有什么所谓的这个不好的方面,有呗,也说变慢了,这个变慢是怎么说呢。
15:13
对,你看咱们原来没有加他的时候呢,那你可以还真看到是不是三个线程就有点像这种并行一样是吧?哎,在操作了,那现在呢,我们加上这个同步以后呢。加上同步以后,我们这个同步的这段代码,你外边呢,有可能是还是并行的,但是在这里边呢,是不是只能有一个线程执行啊啊,那你其他线程都得等着,相当于在这个同步代码块的代码当中呢,实际上相当于是一个单线程了。对吧,哎,这是我们描述一下啊,这是它的一个好处,然后呢,就是说哎操作。哎,操作这个同步哎代码时啊,只能有啊一个线程啊参与哎其他的线程等待。
16:06
哎,这呢,其实哎相当于哎相当于是一个哎单线程的过程啊。哎,这个呢,相对来讲这个就效率低一些,哎,但是即使这样的话呢,我们也必须得用这个同步啊,这你算成一个坏处也行啊,或者叫局限性吧,不能说人家就是坏处啊,叫局限性,嗯。就是你要解决安全问题,只能这样做啊,顺便呢,出现这样问题出现就出现了,因为你会发现呢,咱们全国呢,这个那么多这个窗口都去卖票呢,你你去操作那个票的呢,其实还是就是一瞬间的事儿啊,所以说其实也不受影响啊,就是你这个窗口的话呢,有很多大家说我要从那去那儿啊,选几点的车啊,这块其实花费了很多时间,最后呢,你出票其实就是一下一下的事儿,在那一下的时候呢,是个单线程呢,其实也还好啊行这呢就是咱们这个叫同步代码块的方式呢,来解决了咱们这个叫reable实现的方式的一个安全问题啊。
我来说两句