java多线程:线程的同步与锁

来源:互联网 发布:股票交易数据 编辑:程序博客网 时间:2024/07/24 02:47

<关键字synchronized>

一,同步问题提出

        线程的同步是为了,防止多个线程访问同一个数据对象,对数据造成的破坏。

        比如,两个线程Threa1,Thread2,都操作同一个Foo对象,并且修改Foo对象的数据。

         


两个线程,ThreadA,ThreadB对Foo进行了异步操作,也就是说,在某一段时间,是有两根线程在访问同一块代码,修改代码的数据,我们把这块被多个线程访问,修改数据的代码称为临界资源。为了保证能够实现同步,我们需要知道锁的概念。


二,同步和锁定

       1,锁的原理

        Java中每个对象都有一个内涵i锁

        当程序运行到非静态的synchronized同步方法上时,自动获得和正在执行代码类的当前实例(this 实例)有关的锁。

        获得一个对象的锁也成为获取锁,锁定对象,在对象上锁定或在对象上同步。

        当程序运行到synchronized同步方法或代码块时该对象锁才起作用。

        一个对象只有一个锁,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(返回)锁,这也意味任何其他线程都不能进入

       该对象上的synchronized方法或代码块,知道该锁被释放。也就是说,被synchronized修饰的代码只有一个线程在访问。

       释放锁,是指锁线程退出了synchronized同步方法或者代码块。

       2.关于锁和同步,有下面几个要点

          只能同步方法,不能同步类,和变量。

          每个对象只有一个锁,当提到同步时,应该清楚在什么上同步,或者在哪个对象上同步。

          不必同步类中所以的方法,里,可以同时用于同步和非同步方法。

          如果两个线程要执行一个类红的synchronized方法,并且,两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行,

          另一个需要等待,知道锁被释放,也就是说,如果一个线程在对象上获得一个锁,就没有其他任何线程可以进入类中的任何一个同步方法。

           线程可以获得多个锁,如,在一个对象的同步方法里面调用另一个对象的同步方法,则获取两个对象的同步锁。

          同步锁损坏并发性,应该尽可能缩小同步范围,同步不但可以同步整个方法,还可以同步方法中一部分代码块。

           线程睡眠时,它所持有的任何锁都不会释放。

            public int fix(int y){

            synchronized(this){

            x= x - y;

              }

            }

三,静态方法同步

         要同步静态方法,需要一个用于整个类对象的锁,这个对象就是这个类(xxx.class)

         public static synchronized int setName(String name){

              xxxx.name = name;

}

四,如果线程不能不获得锁会怎么样

        如果线程试图进入同步方法,而其锁已经被占用,则线程在该对象上被阻塞,实质上,线程进入该对象的一种池中,必须在池中等待,直到其锁

        被释放,该线程再次变为可运行为止。

        当考虑阻塞时,一定要注意那个对象正在被用于锁定:

         调用同一个对象中非静态同步方法的线程蒋被阻塞。如果是不同的对象,则每个线程都自己的对象锁,线程间互相不会干涉。

         调用同一个类中的静态同步方法的线程将被彼此阻塞,他们都是锁定再相同的Class对象上。

         静态同步方法和非静态同步方法将永远不会彼此阻塞,因为静态方法锁定在Class对象上,非静态方法锁定再该类的对象上。

         对于同步代码块,要看清楚什么对象已经用于锁定,在同一个对象上进行同步的线程将被彼此阻塞,在不同对象上锁定的线程将一样不会彼此阻塞。

五,何时需要同步

        对于静态字段中可更改的数据,通常使用非静态方法访问。

        对于静态字段中可更改的数据,通常使用静态方法访问。

六,线程安全类

        当一个类已被同步,以保护他的数据时,这个类就是线程安全的类。      

        即使是线程安全的类,也应该特别小心,因为操作的线程时间任然不一定安全。 


七,线程死锁

         死锁对Java来说,是很复杂的,也是很难发现的,当两个线程被阻塞,每个线程在等待另一个线程时就会发生死锁!


八,线程同步小结

        线程的同步的目的是为了保护多个线程访问一个资源时对资源的破坏。

        线程同步方法是通过锁定来实现,每个对象都有且仅有一个锁,这个锁和特定对象关联,线程一旦获取了对象锁,其他访问对象的线程就

        无法再访问该对象的其他同步方法。

        对于静态同步方法,锁是针对这个类的,锁对象是该类的Class 对象,静态和非静态的锁互不干预,一个线程获得锁,当再一个同步方法中

        访问另外对象上的同步方法时,会获取这两个对象锁。

        对于同步,要时刻清醒再那个对象上同步,这事关键。

        编写线程安全的类,需要时刻注意多个线程竞争访问资源的逻辑和安全做出正确的判断,对"原子"操做出分析,并保证"原子"操作期间别的线程无法访问           竞争资源。

         当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。

         死锁是线程之间相互等待锁造成的,再实际中发送的概率非常的小,自己写一个死锁程序,不一定能够实现死锁的效果,但是一旦程序发生死锁,程序            将死掉。

       

        

      


0 0
原创粉丝点击