黑马程序员技术交流社区

标题: 线程同步 [打印本页]

作者: 希望多多    时间: 2013-12-17 10:53
标题: 线程同步
本帖最后由 希望多多 于 2013-12-18 15:19 编辑

线程是如何实现同步的啊?
作者: zzkang0206    时间: 2013-12-17 11:07
1 wait方法:
  该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。
  调用wait方法需要注意几点:
  第一点:wait被调用的时候必须在拥有锁(即synchronized修饰的)的代码块中。
  第二点:恢复执行后,从wait的下一条语句开始执行,因而wait方法总是应当在while循环中调用,以免出现恢复执行后继续执行的条件不满足却继续执行的情况。
  第三点:若wait方法参数中带时间,则除了notify和notifyAll被调用能激活处于wait状态(等待状态)的线程进入锁竞争外,在其他线程中interrupt它或者参数时间到了之后,该线程也将被激活到竞争状态。
  第四点:wait方法被调用的线程必须获得之前执行到wait时释放掉的锁重新获得才能够恢复执行。

2 notify方法和notifyAll方法:
  notify方法通知调用了wait方法,但是尚未激活的一个线程进入线程调度队列(即进入锁竞争),注意不是立即执行。并且具体是哪一个线程不能保证。另外一点就是被唤醒的这个线程一定是在等待wait所释放的锁。
  notifyAll方法则唤醒所有调用了wait方法,尚未激活的进程进入竞争队列。

3 synchronized关键字:
  第一点:synchronized用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。
  第二点:synchronized用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。
  第三点:synchronized修饰一个代码块。类似这样:synchronized(obj) { //code.... }。表示一个线程要执行该代码块,必须获得obj的锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。利用零长度的byte数组对象做obj非常经济。
作者: Y_Y    时间: 2013-12-17 11:08
多线程:
        多线程的同步:        
                多线程并发访问同一个对象(临界资源),如果不对线程进行同步控制,破坏了原子操作(不可再分的操作),则会造成临界资源(两个线程同时访问的资源)的数据不一致。   

                每一个对象都有一个互斥的锁标记和一个锁池。当线程拥有这个对象的锁标记时才能访问这个资源,没有锁标记便进入锁池,保证在同步代码块中只有一个线程,解决了多线程同步控制的问题。
               
                关键字:synchronized        //线程在同步代码中必须采用串行访问
                        synchronized修饰代码块:对括号内的对象object加锁,只有拿到对象锁标记的线程才能进入该代码块。
                                   public void push(char c){
                                        synchronized(object){         //object只要是对象就可以,但必须保证是同一对象
                                                ……
                                                同步代码
                                                ……
                                        }
                                   }
                                   
                        synchronized修饰方法:在整个方法范围内对当前对象的加锁,只有拿到对象锁标记的线程才能执行该方法。尽可能的少用
                                   public synchronized void push(char c) {
                                        ……
                                        同步代码
                                        ……        
                                }
                                      
                一个线程可以同时拥有多个对象的锁标记,锁标记如果过多,就会出现线程等待其他线程释放锁标记,而又都不释放自己的锁标记供其他线程运行的状况,造成死锁。                                

                静态方法可以是同步方法:但是它所锁的并不是当前对象,是类对象。
                抽象方法不能是synchronized同步的方法。
                构造方法不能是synchronized同步的方法。
                        
                线程因为未拿到锁标记而发生阻塞进入锁池(lock pool)。每个对象都有自己的一个锁池的空间,用于放置等待运行的线程。由系统决定哪个线程拿到锁标记并运行
               
                利用Collections类中的synchronizedXxxx(Xxxx ss)方法可以得到相应集合的线程安全的集合
               
                注意:
                        在同步语句块中不能直接操作对象锁正在使用的对象。
                        对象与锁一一对应。
                        同步依赖对象锁,锁对象相同,同步语句串行,锁对象不同,同步语句并行。
                        顺序锁,不要回调,反向打开。
                        能不用同步就不用同步,有数据共享冲突时才使用同步。
               
        等待通知机制:
                线程间通信使用的空间称之为对象的等待对列(wait pool),该队列也是属于对象的空间的。
               
                使用Object类中wait()的方法,在运行状态中,线程调用wait(),此时表示线程将释放自己所有的锁标记和CPU的占用,同时进入这个对象的等待池。等待池的状态也是阻塞状态,只不过线程释放自己的锁标记。只有在对该对象加锁的同步代码块里,才能掉用该对象的wait(),表示线程将会释放所有锁标记,进入等待队列,线程将进入等待队列状态。
               
                一个线程进入了一个对对象加锁的同步代码块,并对该对象调用了wait()方法,释放自己拥有的所有锁标记,进入该对象等待队列,另一个线程获得了该对象的锁标记,进入代码块对该对象调用了notify()方法,就会从等待队列里释放出一线程,释放出的这个线程要继续运行就还要进入那个同步代码块,因为得不到要访问代码块对象的锁标记,而进入该对象的锁池,等待锁标记释放。
               
                什么情况下释放锁:
                        同类代码执行完毕。
                        异常未处理,错误退出。
                        调用wait()。
               
                相关方法:
                        1) wait():交出锁和CPU的占用;
                        2) notify():将从对象的等待池中移走一个任意的线程,并放到锁池中,那里的对象一直在等待,直到可以获得对象的锁标记。
                        3) notifyAll(): 将从等待池中移走所有等待那个对象的线程并放到锁池中,只有锁池中的线程能获取对象的锁标记,锁标记允许线程从上次因调用wait()而中断的地方开始继续运行
                        
                注意:
                        用notifyAll()取代notify(),因为在调用notify()方法时,是由系统决定释放出哪个线程。
                        只能对加锁的资源进行wait()和notify()。
                        判断是否进行等待wait()时,用while代替if来进行判断。

作者: 希望多多    时间: 2013-12-17 11:20
zzkang0206 发表于 2013-12-17 11:07
1 wait方法:
  该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程 ...

这好像不是同步,是线程间的通信吧
作者: zzkang0206    时间: 2013-12-17 11:24
希望多多 发表于 2013-12-17 11:20
这好像不是同步,是线程间的通信吧

也是同步的几种方法呀
作者: 希望多多    时间: 2013-12-17 11:29
zzkang0206 发表于 2013-12-17 11:24
也是同步的几种方法呀

哦,是这样啊,小弟刚学不是很清楚
作者: zzkang0206    时间: 2013-12-17 11:33
希望多多 发表于 2013-12-17 11:29
哦,是这样啊,小弟刚学不是很清楚

在黑马的官网上下载视屏看看  看完之后觉得自己有所了解以后 然后在百度下 看看别人对于线程的具体讲解,及其他知识的具体讲解,多在论坛上逛逛 不懂的记下来 看视屏 找度娘 多动手敲敲代码 我就是这样操作的。
作者: ndfgrivb    时间: 2013-12-18 12:08
标题: 办户口,代办双重户口,办理超生小孩户口,黑户口
本机构成立以来,为全国30多个省市的客户办理计划外的生育入户,办理所在地真实户口,可享受当地的各方福利,保险,就业等,办理需求多重身份证真实身份证的人群提供过帮助,取得了优秀的成绩。有着丰富的操作经验,在全国各地吸收了众多的优秀关系人群。在各方人才储备实力上,我们有着全国最好的人脉关系网和社会政府教育界人才,我们的宗旨是服务于大家,创一流的信誉和优质的服务。
QQ:84213788:http://www.hx3858.com/





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2