首页 > 编程语言 > 详细

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

时间:2019-10-29 14:18:40      阅读:93      评论:0      收藏:0      [点我收藏+]

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获取锁阻塞了,其他线程一直等待,不可中断,非公平锁
 *    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);
        }
    }
}

 

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

原文:https://www.cnblogs.com/moris5013/p/11758414.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!