00:01
各位同学大家好,欢迎继续收看上硅谷GUC高并发编程课程。在上节内容中呢,咱们讲到了通过site关键词,包括lock接口来实现了卖票的例子,我们把代码做一个实现,那下面呢,咱们把这个log接口跟生代的比较,我们再来重复一遍,各位看一下我这个word文档中,那咱看到啊,我这里写到首先第1.look呢是一个什么接口,而写nice呢,是Java中的一个关键字,这是它的第一个不同,另外里边有第二不同,这个不同各位注意啊,奈这个关键字,当它在使用过程中发生异常,那它会怎么样?它会自动释放占有的这个锁,因此不会导致死锁的现象发生,但是lock就不一样了,Lock它不会自动释放锁,就是它不会自动调这个安lo方法,如果说它有异常发生,那这锁也会一直占用,所以说咱就需要把这个lo里。
01:08
起边是往左,代码写到这个发那里边去,包括各位看一下,我们刚才写这个代码中到这个地方。各位看到这个unlo方法调用,我是不是写到了find到里边呀,表示有没有异常,是不是大家都会注意释放,所以这是两个的第二个区别,另外里边有第三个区别,就是lock,它里面有个特点,可以让等待的这个锁的线程响应中断,但是SNE却不行,因为我们使用SNE,它会一直等待这个线程等待下去而不能响应中断,就是它会一直等,中间不能打断,但漏是可以的。另外里边有第四个特点。通过lo呢,我们可以知道这个锁有没有成功获取到,但是SNE却不能得到,因为SNE是自动完成的。另外还有最后一点就是我们用lo也好,用SNE也好,如果说你竞争的资源不是很激烈,那两者的区别基本上是很小的,但是如果说你竞争特别激烈的时候,这个时候lock的性能要远大于S。
02:20
所以这是两者的区别的一个比较,各位把这个给他知道。然后这个说完之后,咱们的第二个知识点,关于这个log接口我们就说完了,那下面我们进入到咱们内容中的第三个知识点,我们叫做线程间的通信,那什么叫线程间的通信呢?因为咱们每次创建线程,咱们看一下是不是都要调里面这个大的方法呀,这大的方法刚才我说过,它是否会马上创建线程,或者我创建线程的顺序是不是不确定的呀?因为这个方法底层掉了一个native,就是交给操作系统去执行,但是我现在我可以让这个线程呢,按照我要求的顺序去执行这个过程,就是我们要讲这个知识点,叫做线程间的通讯,让这个线程按照咱们要求的顺序进行执行,那这个该怎么做,下面给各位我来详细来说一下,我们要讲这个知识点。
03:24
在说这个之前,首先我们看一下这个地方,刚才咱们写这个代码的时候给各位说过,咱们多线程编程步骤一共有上中下三部,刚才咱说的是它的上部,所以现在呢给各位说一下。多线程编程步骤的中部。那我把这个中部就写到我们这里边,给各位把现在来写一下啊,首先咱们要做多远程开发,第一步肯定是固定的创建一个资源类,然后在资源类中创建属性,包括我们的操作方法,然后这个做到之后我们里边的第二步操作。
04:07
给各位讲,这里就是你在资源类那个操作方法中进行三步操作,注意是三步操作,那三步操作,第一步操作我们叫判断。第二步操作叫干活,第三步操作叫做通知,这是我们写的三步,然后这个做完之后再进入到咱们的第三步,第三步就是创建多个线程,然后最终去调用咱们资源类中的方法,然后实现我们最终的这么一个效果,所以这样的话呢,咱就把这个编程步骤中的上部和中部给大家就总结出来了。然后这里边这个判断干活通知到底是什么意思,咱们下面通过一个例子给各位详细来演示一下这个过程。下面呢,我们来写一个关于这个线程间通信的例子,这个例子呢,我们写什么例子给大家说一下啊,比如说我现在啊,我想实现我们有这么两个线程,然后我实现让两线程做件事情实现,对就是这么一个啊对一个初始值。
05:22
是零的这么一个变量做操作,就是两个线程都对同一个变量做操作,那怎么操作?我让两个线程中的其中的一个线程对这个变量,或者说对这个值让它做一个加一操作,然后让另外的这么一个线程。对这个值做一个就是减一的这么一个操作,比如说咱们重复做加一做减一,什么意思呢?给大家说的具体点,比如说我现在啊,有两个线程,一个线程是A。
06:02
一个线程是B,那我实现让A对这个值加一,因为值初入值是零嘛,加一之后是变成一了,当它加一之后,让B的线程对它再减一,减一之后是不是排是零,就是咱们以此类推,让我这里边A的值对它就加一,B对它就减一,就是加一减一,加一减一,以此类推,是咱们重复让它们交替完成多次。A的线程值就是一,B的线程就是零加一减一加一减一依次完成,这是我们要实现一个效果,这个过程就叫线程间的通信。用两个线程对这个值做加一和减一,让他们实验一个就是交替完成的效果。这个啊是咱们要做的例子,那这个例子呢,我们下面就通过线程间的通信方式经完成,那怎么完成给各位我先分析一下,在分析过程中咱也说明一下,我们刚才说这个上中两个步骤,这个并写代码,那咱看怎么做啊,比如说咱们一说代码中等第一步。
07:16
咱是不是写个资源类了,在资源类中呢,我们定义一个属性,属性就是变量等于零的这么一个属性,然后咱们写完之后再写两个方法,一个方法对它加一,一个是不是减一啊,在加一和减一里边,咱们需要做这个操作。什么操作判断、干活、通知,什么叫判断?先判断我的值是零还是一,各位注意啊,如果说变量值是一,零,咱干什么?是不是加一啊?如果值是一是不是就是减一啊,就是判断它是零还是一,比如说我们做这个就是加的方法,那加的方法的时候只有是零是不是才加一,如果你是减的方法只有是一是不是才减一,所以咱们做第一步就是判断,第二步干活,干活什么意思啊?零是不是加一,一是不是减一,加一或者减一就叫干活。第三步叫什么通知,比如现在我A的线程对立值加一了,加一之后是不是要通知B的线程,让B对它是不是要减一,这就叫做判断、干活,包括通知。
08:26
这各位给他知道。然后这个做完之后,等到第三步,那我们就需要创建多个线程,然后调用资源类中的方法,最终完成党内过程。然后这个过程中呢,除了咱们刚才用到那些类和方法之外,还需要用到两个方法,举个例子啊,比如说我现在我在这个加的方法,假如说咱们加的方法叫这个A的方法里边是不是要加一。那你注意咱们什么时候才加一。我变量我写一下啊,就是我现在这个变量值是零。
09:04
咱是不是才加一啊,而我不是零,那我干什么,是不是要等待呀,而等待的话,咱们可以用个方法,比如说咱们一会儿我先用这个个ne实现,那我们要等待的话,咱们找个方法大家看啊,在我们Java浪包里边有个类,这个类叫做object类,这各位应该都知道,然后在object类中大家看看方法。看到这个了吗?是不是叫为的方法导致当前线程等待?所以我强调,当咱们在加的括号中,如果值是零就加一,如果是一的话,那咱们是就wait wait之后,如果这里边我们等待当它变成零,咱们加一,加一之后是不是在通知其他线程,而通知其他线程大家看这方法noify,或者说叫no DeFify o,是不是就能通知加线程,所以咱们现在就通过这些方法,就可以把这个线程间通信的例子,我们最终给它完成出来。
10:09
那下面我就把这例子咱们下面就详细来写一下,然后写的过程中我会通过两种方式实现,第一种方式咱们还是先用这个S这个关键字先实现,然后第二种方式我们再用这个look方式把这个做实现。所以咱们现在把这个直线思路给各位做个分析,从我的分析,大家先知道咱们这个多线程编程的上部和中部,包括咱们要做这个例子,具体该怎么进行实现。
我来说两句