可以同时调用,可以理解为不加synchronized的方法无视这个对象的锁
int count=10; public synchronized void m1(){ count--; System.out.println(Thread.currentThread().getName()+"m1 started 01 : "+count); try { Thread.sleep(10000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"m1 started 02 : "+count); } public /*synchronized*/ void m2(){ try { count--; Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"m2 start ..."+count); } public static void main(String[] args) { Test t = new Test(); new Thread(()->t.m1(),"m1").start(); new Thread(()->t.m2(),"m2").start(); }
String name; Double price; public synchronized void set(String name,Double price){ this.name=name; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } this.price=price; } public Double get(){ return this.price; } public static void main(String[] args) { Test t = new Test(); new Thread(()->t.set("zhangsan",100.00),"m1").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(t.get()); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(t.get()); }
一个线程已经拥有了某个对象的锁,再次申请的时候仍然会得到该对象的锁,也就是说synchronized获得的锁是可以重入的,子类也可以调用父类的同步方法
程序执行过程中如果出现异常,默认情况锁会被释放
所以在并发处理的过程中,有异常要多加小心,不然可能会发生不一致的情况,若是不想释放这个锁则加上try()catch()
这个和JMM有关(Java Memory Model)Java内存模型
在JMM中有一个内存为主内存(我们所说的栈内存、堆内存都可以理解为主内存),每一个线程在执行的过程中都有一个自己的内存,存放自己变量的内存。它会从主内存中读取数据,把数据放进自己的缓冲区内,然后进行操作,然而在没操作完之前,它不会再回到主内存中取读取数据,因为本地已经缓存了数据,操作完之后再写回主内存中。若是读的这条数据加上volatile,这条数据发生变化之后,就会通知其他线程,之前的数据过期了,请重新来主内存中读取数据。
注:volatile不能替代synchronized,volatile只能保证可见性,synchronized技能保证可见性,还能保证原子性,synchronized性能比volatile低
volatile boolean running=true; void m(){ System.out.println("m start"); while (running){ } System.out.println("m end"); } public static void main(String[] args) { Test3 t = new Test3(); new Thread(()->t.m(),"m1").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } t.running=false; }
AtomicXXX类本身方法都是原子性的,但不能保证多个方法连续调用是原子性的。
所是锁的是对象,则对的是堆内存中的对象,若是新new了一个对象,则这个对象已经不是原来的对象了,所以不能新new 这个对象。
原文:https://www.cnblogs.com/gxlaqj/p/11691190.html