java synchronized

关于synchronized的初步使用,你们看拙做

关于synchronized

便可


不过今天,有个朋友问我,若是用synchronized修饰一个类的成员变量会怎么样?

我们看下面的代码

package thread;public class ThreadTestffd { private Integer a = 0; private Integer b = 0; public static void main(String[] args) {  ThreadTestffd test = new ThreadTestffd();  test.A();  test.B(); } public void A() {  new Thread(new Runnable() {   @Override   public void run() {    System.out.println("A线程准备");    synchronized (a) {     System.out.println("A线程开始");     for (int i = 0; i < 10; i++) {      System.out.println("a" + i);      try {       Thread.sleep(500);      } catch (InterruptedException e) {       e.printStackTrace();      }     }    }   }  }).start(); } public void B() {  new Thread(new Runnable() {   @Override   public void run() {    System.out.println("B线程准备");    synchronized (b) {     System.out.println("B线程开始");     for (int i = 0; i < 10; i++) {      System.out.println("b" + i);      try {       Thread.sleep(500);      } catch (InterruptedException e) {       e.printStackTrace();      }     }    }   }  }).start(); }}

    1

最后的结果是先等a方法运行完以后,才打印出来b线程开始,固然"b线程准备"很早就打印了

这说明什么,我猜想就是:

用synchronized修饰成员变量,就直接限制了这个对象实例,synchronized(成员变量)就等于synchronized(this)


那若是有两个对象呢?

就像我把代码改为:

 private  Integer a = 0; private  Integer b = 0; public static void main(String[] args) {  ThreadTestffd test = new ThreadTestffd();  test.A();  ThreadTestffd test2 = new ThreadTestffd();  test2.B(); }

    1

那结果应该是什么样的?

应该是交错打印的么?

应该是的,毕竟两个对象么

可是结果不是,结果是先打印a而后打印b

卧槽?日了狗了!

我脑子突然想到一个问题,要不咱换一个成员变量?

 private Person a=new Person(); private Person b=new Person(); public static void main(String[] args) {  ThreadTestffd test = new ThreadTestffd();  test.A();  test.B(); }

    1

最后的结果是交替打印,Person就是一个简单的pojo类

我靠什么状况?integer和pseron的结果不同

后来,我突然想到了integer是有缓存的,以下:

    public static Integer valueOf(int i) {        assert IntegerCache.high >= 127;        if (i >= IntegerCache.low && i <= IntegerCache.high)            return IntegerCache.cache[i + (-IntegerCache.low)];        return new Integer(i);    }

    1

在-128到127直接的都是一个对象

也就是说最开始的代码,虽然一个锁a一个锁b,可是锁的都是同一个对象

后面的,把ab改为了person,就交替打印了,由于a和b压根就不是同一个对象

因此上面的结论:

用synchronized修饰成员变量,就直接限制了这个对象实例,synchronized(成员变量)就等于synchronized(this)

也是不对的

synchronized(成员变量A)与synchronized(成员变量B)是没有关系的,他们互补干扰

其实也对,既然用锁,那就一个对象么,一个a一个b什么鬼?

伙计说:我就测试测试....


其实这篇博客的名字应该叫谈谈integer的缓存的

缓存

========================================================多线程

这里主要涉及到类对象(static方法),对象方法(非static方法)ide

咱们知道,当synchronized修饰一个static方法时,多线程下,获取的是类锁(即Class自己,注意:不是实例);测试

当synchronized修饰一个非static方法时,多线程下,获取的是对象锁(即类的实例对象)this

因此,当synchronized修饰一个static方法时,建立线程不论是new JoinThread()仍是new Thread(new JoinThread()),在run方法中执行inc()方法都是同步的;atom

相反,当synchronized修饰一个非static方法时,若是用new JoinThread()仍是new Thread(new JoinThread())方式建立线程,就没法保证同步操做,由于这时线程

inc()是属于对象方法,每一个线程都执有一个独立的对象实例new JoinThread(),因此多线程下执行inc()方法并不会产生互斥,也不会有同步操做。对象

 

另外若是考虑到变动的原子操做,可以使用atomic包下面的包装对象,这些对象都是对volatile修饰变量的一种延伸,可保证变量的原子操做而不用去同步方法或继承

代码块是否同步同步

 

==============================

必须注意的地方:一、某个对象实例内,synchronized aMethod(){}关键字能够防止多个线程访问对象的synchronized方法(若是一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不一样的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样能够同时访问相同类的另外一个对象实例中的synchronized方法.二、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类须要你显式的指定它的某个方法为synchronized方法;三、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另外一个线程仍然能够访问该object中的非synchronized(this)同步代码块。四、尤为关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其余线程对object中全部其它synchronized(this)同步代码块的访问将被阻塞。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就得到了这个object的对象锁。结果,其它线程对该object对象全部同步代码部分的访问都被暂时阻塞。

相关文章
相关标签/搜索