近段为了实现一个功能,在树结构中,修改某个节点名称时,需要同时修改这个节点所有子节点的节点全路径属性字段(类似"父父节点名称/父节点名称/子节点名称/子子节点名称"的构造)。因为在构造Update语句时,需要递归去查询子节点以及构造全路径的值,需要花费了一定的时间,等批量执行update语句时,可能子节点的某个子节点的名称又改变了,会引起冲突,故用到了synchronized,顺便了解了下实现方式,原理没深入了解,在此记录以便日后查看。
-----------------------------------------------------我是正文分割线--------------------我是正文分割线---------------------------
本文主要列举不同的同步方式,以及我理解的使用范围。
众所周知,同步分为两种用法:同步方法、与同步块。
一、同步块
1.1 类同步(非静态方法)
· 实现方式:
1 public class JustPlayServiceImplSyn2 { 2 3 public JustPlayServiceImplSyn2(){ 4 5 } 6 private static int flag = 1; 7 public void operate() { 8 synchronized(JustPlayServiceImplSyn2.class){ 9 flag++; 10 try { 11 // 增加随机性,让不同线程能在此交替执行 12 Thread.sleep(new Random().nextInt(5)); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 flag--; 17 System.out.println("Thread: " + Thread.currentThread().getName() 18 + " /Current flag: " + flag);19 }20 }21 }
· 测试代码:
1 public class JustPlay { 2 /** 3 * @param args 4 */ 5 public static void main(String[] args) { 6 new Thread("Thread-01") { 7 public void run() { 8 new JustPlayServiceImplSyn2().operate(); 9 } 10 }.start(); // 启动第一个线程11 12 new Thread("Thread-02") { 13 public void run() { 14 new JustPlayServiceImplSyn2().operate();15 } 16 }.start(); // 启动第一个线程17 }18 }
· 使用范围:多对象多线程的同步。
使用范围最广,代码也简单,在需要同步的代码块上加上synchronized关键字,并在括号类用[类名.class]就行。
1.2 this同步(非静态方法)
· 实现方式:
1 public class JustPlayServiceImplSyn2 { 2 3 public JustPlayServiceImplSyn2(){ 4 5 } 6 private static int flag = 1; 7 public void operate_this() { 8 synchronized(this){ 9 flag++; 10 try { 11 // 增加随机性,让不同线程能在此交替执行 12 Thread.sleep(new Random().nextInt(5)); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 flag--; 17 System.out.println("Thread: " + Thread.currentThread().getName() 18 + " /Current flag: " + flag);19 }20 }21 }
· 测试代码:
1 public class JustPlay { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 final JustPlayServiceImplSyn2 justplayserviceimplsyn2= new JustPlayServiceImplSyn2(); 8 for(int i=0;i<100;i++){ 9 new Thread("Thread-001"){10 public void run() {11 justplayserviceimplsyn2.operate_this();12 }13 }.start();14 new Thread("Thread-002"){15 public void run() {16 justplayserviceimplsyn2.operate_this();17 }18 }.start();19 }20 }
· 使用范围:单对象多线程的同步。
在synchronized关键字后的括号内用this关键字。使用[this]同步时需要是同一对象的才能同步,多对象时是同步失败的。因为同步是对this对象锁,不同对象时锁互不影响
1.3 静态对象同步(非静态方法)
· 实现方式:
1 public class JustPlayServiceImpl { 2 private static JustPlayServiceImpl myobj = null; 3 4 private JustPlayServiceImpl(){ 5 6 } 7 public static JustPlayServiceImpl createJustPlayServiceImpl(){ 8 if(myobj==null){ 9 myobj = new JustPlayServiceImpl();10 }11 return myobj;12 }13 private static int flag = 1;14 public void operate() { 15 synchronized(myobj){16 flag++; 17 try { 18 // 增加随机性,让不同线程能在此交替执行 19 Thread.sleep(new Random().nextInt(5)); 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 } 23 flag--; 24 System.out.println("Thread: " + Thread.currentThread().getName() 25 + " /Current flag: " + flag);26 }27 }28 }
· 测试代码:
1 public class JustPlay { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 8 for(int i=0;i<100;i++){ 9 new Thread("Thread-01") { 10 public void run() { 11 JustPlayServiceImpl.createJustPlayServiceImpl().operate()) } 12 }.start(); // 启动第一个线程13 new Thread("Thread-02") { 14 public void run() { 15 JustPlayServiceImpl.createJustPlayServiceImpl().operate() } 16 }.start(); // 启动第二个线程17 }
· 使用范围:单体类单对象多线程的同步。
因为同步是对对象的同步锁,只要保证同步块对象唯一,就能实现同步。偷点懒,我直接将类变成了单体类,然后将唯一对象给锁了。(ps:怎么感觉有点鬼畜。。。哈哈哈)
二、同步方法
2.1 静态方法同步
· 实现方式:
1 public class JustPlayServiceImplSyn2 { 2 3 public JustPlayServiceImplSyn2(){ 4 5 } 6 private static int flag = 1; 7 public synchronized static void operate_static(){ 8 flag++; 9 try { 10 // 增加随机性,让不同线程能在此交替执行 11 Thread.sleep(new Random().nextInt(5)); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 flag--; 16 System.out.println("Thread: " + Thread.currentThread().getName() 17 + " /Current flag: " + flag);18 }19 }
· 测试代码:
1 public class JustPlay { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 for(int i=0;i<100;i++){ 8 new Thread("Thread-01") { 9 public void run() { 10 JustPlayServiceImplSyn2.operate_static();11 } 12 }.start(); // 启动第一个线程13 14 new Thread("Thread-02") { 15 public void run() { 16 JustPlayServiceImplSyn2.operate_static();17 } 18 }.start(); // 启动第一个线程19 }20 }21 }
· 使用范围:静态方法单对象多线程的同步。
再次说[因为同步是对对象的同步锁],而且调用静态方法绑定的是类而不是对象,所以,同步了静态方法,就是将相当于将类给锁了,然后就同步了。原理与[1.1 类同步(非静态方法)]一致。
2.2 非静态方法同步
2.2.1 单体类非静态方法同步
· 实现方式:
1 public class JustPlayServiceImpl { 2 private static JustPlayServiceImpl myobj = null; 3 4 private JustPlayServiceImpl(){ 5 6 } 7 public static JustPlayServiceImpl createJustPlayServiceImpl(){ 8 if(myobj==null){ 9 myobj = new JustPlayServiceImpl();10 }11 return myobj;12 }13 private static int flag = 1;14 15 //单体类 此种同步方式有效16 public synchronized void operate2() { 17 flag++; 18 try { 19 // 增加随机性,让不同线程能在此交替执行 20 Thread.sleep(new Random().nextInt(5)); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 flag--; 25 System.out.println("Thread: " + Thread.currentThread().getName() 26 + " /Current flag: " + flag);27 }28 }
· 测试代码:
1 public static void main(String[] args) { 2 3 for(int i=0;i<100;i++){ 4 new Thread("Thread-01") { 5 public void run() { 6 JustPlayServiceImpl.createJustPlayServiceImpl().operate2(); 7 } 8 }.start(); // 启动第一个线程 9 10 new Thread("Thread-02") { 11 public void run() { 12 JustPlayServiceImpl.createJustPlayServiceImpl().operate2();13 } 14 }.start(); // 启动第一个线程15 }16 }17 }
· 使用范围:单体类单对象多线程的同步。
原理同[1.3 静态对象同步(非静态方法)]
2.2.2 非单体类非静态方法同步
· 实现方式:
1 public class JustPlayServiceImplSyn2 { 2 3 public JustPlayServiceImplSyn2(){ 4 5 } 6 private static int flag = 1; 7 //适用于单对象多线程 8 public synchronized void operate2() { 9 flag++; 10 try { 11 // 增加随机性,让不同线程能在此交替执行 12 Thread.sleep(new Random().nextInt(5)); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 flag--; 17 System.out.println("Thread: " + Thread.currentThread().getName() 18 + " /Current flag: " + flag);19 }20 }
· 测试代码:
1 public class JustPlay { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 final JustPlayServiceImplSyn2 justplayserviceimplsyn2= new JustPlayServiceImplSyn2(); 8 for(int i=0;i<100;i++){ 9 new Thread("Thread-001"){10 public void run() {11 justplayserviceimplsyn2.operate2();12 }13 }.start();14 new Thread("Thread-002"){15 public void run() {16 justplayserviceimplsyn2.operate2();17 }18 }.start();19 }20 }
· 使用范围:单对象多线程的同步。
原理同[1.2 this同步(非静态方法)]
总结:对于网页用ajax方式多次调用的class,因为是多线程且不可控为单一对象,若想同步:解决方案是:1.1、1.3、2.1、2.2.1;对于1.2和2.2.2,调用的对象必须是保持同一个才会同步。
PS:觉得应该还有其他方式,隐隐的这么觉得。。。。。哈哈哈哈哈哈
------------------------------------结束的分割线--------------结束的分割线------------------有机会再去了解同步的底层原理去了----那时候再写原理------またね!---