synchronized同步方法

『线程安全』与『非线程安全』是学习多线程技术时一定会遇到的经典问题。『非线程安全』其实当多个线程访问同一个对象中的成员变量时产生的,产生的后果就是『脏读』,就是取到的数据其实是被更改过的。而『线程安全』就是以获取的成员变量的值是经过同步处理的,不会出现脏读的现象。

局部变量是线程安全的

public class Demo01 {
    public static void main(String[] args) {
        Demo01Service service = new Demo01Service();
        Thread t1 = new Demo01ThreadA(service);
        t1.start();
        Thread t2 = new Demo01ThreadB(service);
        t2.start();
    }
}

class Demo01Service{
    public void add(String username){
        int num = 0;
        if ("a".equals(username)){
            num = 100;
            System.out.println("a set over");
            // 等待另外一个线程修改num的值
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else {
            num = 200;
            System.out.println("b set over");
        }
        System.out.println("username=" + username + ", num=" + num);
    }
}

class Demo01ThreadA extends Thread{
    private Demo01Service service;
    public Demo01ThreadA(Demo01Service service){
        this.service = service;
    }

    @Override
    public void run() {
        service.add("a");
    }
}
class Demo01ThreadB extends Thread{
    private Demo01Service service;
    public Demo01ThreadB(Demo01Service service){
        this.service = service;
    }

    @Override
    public void run() {
        service.add("b");
    }
}

局部变量不存在非线程安全问题,永远都是线程安全的。这是由局部变量是私有的特征所造成的。

成员变量不是线程安全

public class Demo02 {
    public static void main(String[] args) {
        Demo02Service service = new Demo02Service();
        Thread t1 = new Demo02ThreadA(service);
        Thread t2 = new Demo02ThreadB(service);
        t1.start();
        t2.start();
    }
}

class Demo02Service {
    private int num;
    synchronized public void add(String username){
        if ("a".equals(username)){
            num = 100;
            System.out.println("a is set");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else{
            num = 200;
            System.out.println("b is set");
        }
        System.out.println("username=" + username + ", num=" + num);
    }
}

class Demo02ThreadA extends Thread{
    private Demo02Service service;
    public Demo02ThreadA(Demo02Service service){
        this.service = service;
    }

    @Override
    public void run() {
        service.add("a");
    }
}

class Demo02ThreadB extends Thread{
    private Demo02Service service;
    public Demo02ThreadB(Demo02Service service){
        this.service = service;
    }

    @Override
    public void run() {
        service.add("b");
    }
}

如果有两个线程同时操作业务对象中的成员变量,可能会产生『非线程安全』问题,需要在方法前使用关键字synchronized进行修饰。

多个对象使用多个对象锁

public class Demo03 {
    public static void main(String[] args) {
        Demo03Service service1 = new Demo03Service();
        Demo03Service service2 = new Demo03Service();

        Thread t1 = new Demo03ThreadA(service1);
        Thread t2 = new Demo03ThreadB(service2);
        t1.start();
        t2.start();
    }
}

class Demo03Service {
    private int num;
    synchronized public void add(String username){
        if ("a".equals(username)){
            num = 100;
            System.out.println("a is set");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else{
            num = 200;
            System.out.println("b is set");
        }
        System.out.println("username=" + username + ", num=" + num);
    }
}

class Demo03ThreadA extends Thread{
    private Demo03Service service;
    public Demo03ThreadA(Demo03Service service){
        this.service = service;
    }

    @Override
    public void run() {
        service.add("a");
    }
}

class Demo03ThreadB extends Thread{
    private Demo03Service service;
    public Demo03ThreadB(Demo03Service service){
        this.service = service;
    }

    @Override
    public void run() {
        service.add("b");
    }
}

synchronized取得的锁都是对象锁,而不是把一段代码或方法作为锁,所以那个线程先执行带synchronized关键字修饰的方法,哪个方法就持有该方法所属对象的锁,其它线程只能呈等待状态,前提是多个线程访问的是同一个对象。如果多个线程访问多个对象,JVM会创建出多个对象锁。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值