被synchronized修饰的方法调用了没有被synchronized修饰的方法,是否是线程安全

时间:2021-05-17 20:19:42

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();
} 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();
Thread a = new MyThread(p, ,latch);
Thread b = new MyThread(p, , latch);
a.start();
b.start();
latch.countDown(); }
} class People { public synchronized void a() {
for (int i = ; i < ; i++) {
System.out.print("A");
try {
Thread.sleep();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} } public synchronized void b() {
for (int i = ; i < ; i++) {
System.out.print("B");
try {
Thread.sleep();
} 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 == )
p.a();
else if (c == )
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 = ;
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() != this.address.charAt()) {
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);
}
}
}