被synchronized修饰的方法调用了没有被synchronized修饰的方法,是否是线程安全
1 被synchronized修饰的方法调用了没有被synchronized修饰的方法,是否线程安全?
/** * (1)被synchronized修饰的方法调用了没有被synchronized修饰的方法,是否线程安全? * (2)线程安全问题都是由全局变量及静态变量引起的,若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的; * 若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能导致数据不一致 * (3)线程安全是指多个线程在执行同一段代码的时候采用加锁机制,线程不安全就是不提供加锁机制保护 * (4)在下面的例子中,如果method2方法都是通过method1调用的,那么程序执行没有问题,是线程安全的,但是method2也有可能同时被其他的线程调用,可能会对全局变或者静态变量进行修改,所以说method2线程不安全 */ public class SynchronizedDemo1 { public static void main(String[] args) { new Thread(() -> { method1(); }).start(); new Thread(() -> { method2(); }).start(); } private static synchronized void method1() { method2(); } private static void method2() { System.out.println(Thread.currentThread().getName() + "进入非Synchronized方法"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "结束非Synchronized方法"); } }
2多个方法同步
/** * synchronized可以实现方法的同步,a()和b()方法同步了,因为他们使用的是同一的对象 * 总结synchronized和lock的区别 * (1)synchronized关键字不能继承,如果在父类中的某个方法使用了synchronized关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的, * 而必须显式地在子类的这个方法中加上synchronized关键字才可以 * (2)synchronized是jvm内置锁,当获取锁的线程执行完同步代码或者发生异常,jvm会释放锁,两个线程争抢锁的过程中,a获取锁阻塞了,其他线程一直等待,不可中断,非公平锁,可重入,假如不可重入,
* 那么1个类的synchornized方法不能调用本类其他synchornized方法,也不能调用父类中的synchornized方法 * lock锁是显示锁,锁可中断,也可设置锁的等待时长,获取锁后必须手动释放锁,可以是公平锁也可以是非公平锁 */ public class SynchronizedDemo2 { public static void main(String[] args) { People p = new People(); CountDownLatch latch = new CountDownLatch(1); Thread a = new MyThread(p, 1,latch); Thread b = new MyThread(p, 2 , latch); a.start(); b.start(); latch.countDown(); } } class People { public synchronized void a() { for (int i = 0; i < 50; i++) { System.out.print("A"); try { Thread.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public synchronized void b() { for (int i = 0; i < 50; i++) { System.out.print("B"); try { Thread.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } class MyThread extends Thread { People p; int c; CountDownLatch latch; MyThread(People p, int c ,CountDownLatch latch) { this.p = p; this.c = c; this.latch = latch; } @Override public void run() { try { latch.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (c == 1) p.a(); else if (c == 2) p.b(); } }
3线程不安全的例子
/** * 多个线程调用pass方法时,会对共享数据name和address发生修改,会造成数据不一致,线程不安全 */ public class SynchronizedDemo3 { public static void main(String[] args) { Gate gate = new Gate(); User bj = new User("Baobao", "Beijing", gate); User sh = new User("ShangLao", "ShangHai", gate); User gz = new User("GuangLao", "GuangZhou", gate); bj.start(); sh.start(); gz.start(); } } class Gate { private int counter = 0; private String name = "Nobody"; private String address = "Nowhere"; public synchronized void pass(String name, String address) { this.counter++; this.name = name; this.address = address; verify(); } private void verify() { if (this.name.charAt(0) != this.address.charAt(0)) { System.out.println("*******BROKEN********" + toString()); } } public String toString() { return "No." + counter + ":" + name + "," + address; } } class User extends Thread { private final String myName; private final String myAddress; private final Gate gate; public User(String myName, String myAddress, Gate gate) { this.myName = myName; this.myAddress = myAddress; this.gate = gate; } @Override public void run() { System.out.println(myName + " BEGIN"); while (true) { this.gate.pass(myName, myAddress); } } }