关于JAVA的synchronized关键字,简便记忆!

synchronized关键字英文直译过来为“同步”,同步在java多线程里也可以理解为“排队”。当然它也有一个优雅的名字“互斥锁”。

synchronized可以对共享资源进行锁定,同时一刻只有一个线程可以操作它,等一个线程操作完了,再把锁释放,让下一个线程操作。这样可以保证“线程安全”。

其实结合现实生活我们不难理解,比如一辆车在同一时刻的驾驶员只有一个,能操作这辆车的也只有驾驶员自己,要是有两个人同一时间开同一辆车的话,你转一下方向盘,他转一下方向盘,那不就乱套了吗,肯定是要出事故的呀。

放在java中,如果有一个资源 i 是被线程A和线程B共享的,两个线程都要对其进行i++操作。我们知道i++这个表达式并不是原子性的,要先读取i的值,再修改。正常情况下两个线程都对其i++了,那么结果应该是2。

如果有这么一种情况 i 的初始值为0,线程A读取i的值还没来得及进行修改,线程B就已经读取到i的值了,并且在A之前进行修改,这时 i 的值被B修改为1,B修改完A才进行修改操作,那么这时A读取到的值还是B做修改之前的值0,那么此时A做修改只会基于一开始读取到的0修改加一。那么线程A和B进行的修改都是基于初始值为0修改的。这样就造成了数据错误。

如何解决这种线程不安全的问题呢?用synchronized关键字。

synchronized关键字最主要有以下3种应用方式

修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁

package tongbu;

public class one implements Runnable{
    static int i=0;
    @Override
    public void run() {
        for (int j=1;j<=10000;j++){
            jia();
        }
    }
    public synchronized void jia(){
        i++;
    }

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

修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁

package tongbu;

public class one implements Runnable{
    static int i=0;
    @Override
    public void run() {
        for (int j=1;j<=10000;j++){
            jia();
        }
    }
    public static synchronized void jia(){
        i++;
    }

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

修饰静态方法和实例方法的区别是,前者可以实例化两个对象,后者只能实例化一个对象。

前者看似实例化两个对象,但由于jia()是static修饰的,两个对象操作的都是jvm里的同一个方法。

修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。

package tongbu;

public class one implements Runnable{
    static one one=new one();
    static int i=0;
    @Override
    public void run() {
        synchronized (one){
        for (int j=1;j<=10000;j++){
            i++;
        }}
    }


    public static void main(String[] args) throws InterruptedException {
        //one one= new one();
        Thread t1=new Thread(one);
        Thread t2=new Thread(one);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}
synchronized括号里放共享资源,可以是this,类的实例化对象。

因为同步锁锁的是共享的资源嘛,所以当然要放共享资源啦。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值