锁重入, 对象synchronized 当线程A 得到了 对象锁,再次请求对象时,是可以再次获取 这个对象锁的
package com.study.thread; public class CongRuSuo { public synchronized void method1(){ System.out.println("metho1"); method2(); } public synchronized void method2(){ System.out.println("metho2"); method3(); } public synchronized void method3(){ System.out.println("metho3"); } public static void main(String[] args) { CongRuSuo t1 = new CongRuSuo(); new Thread(new Runnable() { @Override public void run() { t1.method1(); } }).start(); } }
举例2:
package com.study.thread; class Parent{ public static int i=10; public synchronized void downParent(){ i--; try { System.out.println("parent:" + i); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public class CongRuSuo1 extends Parent{ public synchronized void downSon(){ while (i>0){ try { i--; System.out.println("son:" + i); Thread.sleep(1000); super.downParent(); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { CongRuSuo1 t1 = new CongRuSuo1(); new Thread(new Runnable() { @Override public void run() { t1.downSon(); } }).start(); } }
输出结果
线程中出现错误如何处理,举例如下:
package com.study.thread; public class SyncException { private int count=0; public synchronized void sayCount(){ while (true){ count ++ ; try { Thread.sleep(100); System.out.println(count); } catch (InterruptedException e) { e.printStackTrace(); } if (count==10){ try { Integer.parseInt("a"); } catch (Exception e){ e.printStackTrace(); System.out.println("log 日志"); continue; } } } } public synchronized void method3(){ System.out.println("metho3"); } public static void main(String[] args) { SyncException t1 = new SyncException(); new Thread(new Runnable() { @Override public void run() { t1.sayCount(); } }).start(); } }
其中任务失败了,线程会继续往下走,一般处理方法是 日志记录下来
字符串不要做锁
synchronized(“abc”) 这样是有问题的 可以改成这样 synchronized(new String(“abc”))
如果字符串做锁,程序中不要修改 这个锁
Person person = new Person();
synchronized(person ) 两个线程 线程A 修改了 person 的name 属性,是不影响 锁的持有的,线程B 还是只有A 结束的时候才能获取到锁