理解Java中的synchronized关键字

理解synchronized的含义

synchronized是实现java同步机制的锁,线程进入同步代码块和方法是,会获取该锁,当结束同步代码块和方法时会释放该锁。当同步代码块和方法加锁时,只允许一个线程对它进行访问,另一个线程若想对它访问必须等上一个进程释放该锁,下一个线程才会获得该锁。

修饰普通方法

修饰普通方法:是对实例化对象加锁。

public class SynchronizedDemo {

    public static void main(String[] args) throws Exception {
        ClassA a = new ClassA();

        Thread t1 = new Thread(a);
        Thread t2 = new Thread(a);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(a.i);
    }

}
public class ClassA implements Runnable {
     static int i = 0;

    public  synchronized void a() {
        i++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 2000; i++) {
            a();
        }
    }

}

实例化了一个ClassA的实例,并创建了两个线程,若未加同步锁,第二个线程在第一个线程读取旧值并会写新值之前读取i的值,就会造成线程安全失败。所以a方法必须加锁,保证线程安全。对a方法加synchronized其实就是就ClassA的的锁。

修饰静态方法

修饰静态方法:是对类对象加锁。
修改SynchronizedDemo 类中的代码:

public class SynchronizedDemo {

    public static void main(String[] args) throws Exception {
        ClassA a1 = new ClassA();
        ClassA a2 = new ClassA();
        Thread t1 = new Thread(a1);
        Thread t2 = new Thread(a2);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(ClassA.i);
    }

}

若是创建两个实例并开启两个线程去访问a方法,也会造成线程安全失败的问题,因为创建了两个实例化对象,意味着有两个不同的实例的对象锁。尽管在a方法上加了synchroinized也会造成线程安全失败。解决这个问题就需要在类对象加锁,无论无论创建多少个实例但是类对象只有一个,需要synchronized加在静态方法上。

public class ClassA implements Runnable {
     static int i = 0;

    public static synchronized void a() {
        i++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 2000; i++) {
            a();
        }
    }

}

修饰同步代码块

修饰同步代码块:是对指定对象加锁。

public class SynchronizedDemo {

    public static void main(String[] args) throws Exception {
        ClassA a = new ClassA();
        Thread t1 = new Thread(a);
        Thread t2 = new Thread(a);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(a.i);
    }

}
public class ClassA implements Runnable {
     static int i = 0;

    public  void a() {
        i++;
    }

    @Override
    public void run() {
        synchronized (this) {
            for (int i = 0; i < 2000; i++) {
                a();
            }
        }
    }

}

修饰同步代码块对当前对象加锁,当有其他携带该对象的锁的线程进入synchronized修饰的代码块时,必须等当前线程释放该锁之后才可以进入。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值