- 方法内的变量线程安全(方法内部变量具有私有性)
- 实例变量(类下的直接定义的变量)非线程安全(可通过对 *** 作方法加锁解决)
class MyEntity6 { private int num = 10; // 加锁解决线程不安全问题 synchronized public void add(int addNum) { this.num += addNum; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("num = " + num); } } public class StudyThreads6线程安全 { public static void main(String[] args) { MyEntity6 myEntity6 = new MyEntity6(); Thread t1 = new Thread() { @Override public void run() { myEntity6.add(100); } }; Thread t2 = new Thread() { @Override public void run() { myEntity6.add(100); } }; t1.start(); t2.start(); } }资源不共享时候无需加锁
当资源不共享时候,各线程有自己的相应的变量,不加锁多线程之间也不会相互影响。
脏读(写加锁可以解决变量交叉造成的不安全的问题,读变量时候也可能造成不安全)- 脏读即在读的时候此时的变量已经被其他线程更改了
- 可以通过在读方法上加锁来解决(即在读和写方法上都加锁)
- synchronize锁的是对象,当共享实例变量时候传入的是同一个对象,synchronize会对这个对象加锁。
- 在被锁的方法中调用本类中其他加锁的方法时候,锁会自动重入进来
- 锁重入支持在父子继承
- 如果不能锁重入则会造成死锁(当前方法持有锁,方法内部调用的方法请求锁)
当出现异常时候锁会自动释放
同步不能继承父类方法已经同步之后,子类方法需要重写加入synchronize关键字才能实现同步功能,否则不是同步方法。
synchronize(对象),针对对象加锁,如果对象不一样则相应的方法或代码块可以异步执行- synchronize针对对象加锁,传入对象不一样则锁互不影响
- synchronize(this) {}对当前对象加锁
- synchronize修饰静态方法时,是对拥有方法的class上锁;而synchronize关键字加到非static方法上时,是给对象上锁。(代码如下)
- 对class上锁对所有实例都起作用
- synchronize(x.class) 与synchronize static作用一样,都是给对象上锁
printA() printB() 方法是对class加锁,printC()是给对象上锁。锁对象不一样 C与AB不同步:
// synchronize修饰静态方法加锁是对class上锁 // synchronize修饰非静态方法是对对象上锁 // 验证上锁不同如下 class Service { public synchronized static void printA() { try { System.out.println("线程名字:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis() + " 进入A方法。"); Thread.sleep(3000); System.out.println("线程名字:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis() + " 离开A方法。"); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized static void printB() { try { System.out.println("线程名字:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis() + " 进入B方法。"); Thread.sleep(3000); System.out.println("线程名字:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis() + " 离开B方法。"); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void printC() { try { System.out.println("线程名字:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis() + " 进入C方法。"); Thread.sleep(3000); System.out.println("线程名字:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis() + " 离开C方法。"); } catch (InterruptedException e) { e.printStackTrace(); } } } public class StudyThreads7synchronize给静态方法加锁 { public static void main(String[] args) { Service myService = new Service(); Thread threadA = new Thread(() -> myService.printA()); Thread threadB = new Thread() { @Override public void run() { myService.printB(); } }; Thread threadC = new Thread() { @Override public void run() { myService.printC(); } }; threadA.setName("A"); threadB.setName("B"); threadC.setName("C"); threadA.start(); threadB.start(); threadC.start(); } }
输出结果:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)