初遇“synchronized"

故事搞起来~

从今天开始,姑娘我将要回归“起跑线”,含着眼泪默默的将大学老师奋笔疾书教过的“理论”以及工作N年后并曾未总结过的“实战经验”一并拾起来,我要向专业再靠近一步,近一步......心里默默叨念:我不仅可以靠颜值吃饭,更可以在实力的路上越走越远......

这一切的一切动力源于两个原因:1·看到一个毕业不久(好像是哈,反正比我小)的小弟弟在各大网站及b站发表的系列文章,其广度其深度让已经毕业四年的我深感惭愧(姑娘我也是有实力的);2·最近入手一份“价值不菲”(没有多贵哈,利用好了决定价值不菲)的学习资料,出于心疼钱,我决定好好学习,天天向上😭😭

 


 正文还是要有滴~

说起“synchronized",我们会想到什么呢?锁?重量级锁?volatile?reentrantLock ......一切的一切都源于我们的并发与多线程,但说实话,工作的这几年,依旧没有透彻的搞明白并发多线程,但这依旧不影响自己建立这样的知识节点树(之前可能会怕别人嘲笑自己的无知而害怕说错,现在我倒认为:说错没关系,脑子里有错误的理解也没关系,因为随着不断的学习,脑子里的那张网图会被不断更新与替换)

今天只是初遇,毕竟第一次见面,咱就不问人家几套房,几辆车了吧,咱就看看帅不帅,眼睛大不大,鼻子挺不挺,它不香嘛~

是什么

synchronized:Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。目的就是保证多个线程之间访问资源的同步性。

当然,synchronized是有发展阶段的,Java1.6之前,synchronized属于重量级锁,但在之后,在不断的优化过程中,如偏向锁、轻量级锁、自旋锁等技术来减少锁操作的开销。这一部分我们在接下来的系列文章慢慢讲~崩着急~先跟着姐姐一步步走~这一篇我们只讲最最基础的,并证明讲的是对滴

怎么用

synchronized关键字最主要的三种使用方式:

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

  2. 修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例

  3. 修饰代码块: 虽作用于某代码块上,但锁定的对象依旧是对象实例,同修饰实例方法

总结:

synchronized锁定的对象只有两种:1.类的实例 2.类对象(类锁)。当线程1访问同步静态方法时,是允许线程2同时访问该实例对象的同步非静态方法的。因为线程1和2占用的并不是同一把锁,并不会互斥

怎么证明我说的对呢

  1. 证明“修饰实例方法”和“修饰代码块”的锁定对象是一致的

    
    public class SyncTest {
    
        public void test1() {
            //synchronized(this)锁定的是当前类的实例,这里锁定的是SyncTest类的实例
            //synchronized(this) 效果等同于在方法上使用 synchronized
            synchronized (this) {
                System.out.println("t1 start");
                try {
                    for (int i = 1; i < 5; i++) {
                        TimeUnit.SECONDS.sleep(i);
                        System.out.println("t1 sleep " + i);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t1 end");
            }
        }
    
        public synchronized void test2() {
            System.out.println("t2 start");
            System.out.println("t2 end");
        }
    
    
        public static void main(String[] args) {
            SyncTest demo2 = new SyncTest();
            //证明1
            new Thread(demo2::test1).start();
            new Thread(demo2::test2).start();
        }
    }
    

  2. 证明“修饰实例方法”(修饰代码块)与“修饰静态方法”锁定对象不一致

    
    public class SyncTest {
    
        public void test1() {
            //synchronized(this)锁定的是当前类的实例,这里锁定的是SyncTest类的实例
            //synchronized(this) 效果等同于在方法上使用 synchronized
            synchronized (this) {
                System.out.println("t1 start");
                try {
                    for (int i = 1; i < 5; i++) {
                        TimeUnit.SECONDS.sleep(i);
                        System.out.println("t1 sleep " + i);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t1 end");
            }
        }
    
        public synchronized static void test3() {
            System.out.println("t3 start");
            System.out.println("t3 end");
        }
    
        public static void main(String[] args) {
            SyncTest demo2 = new SyncTest();
            new Thread(demo2::test1).start();
            new Thread(SyncTest::test3).start();
        }
    }
    

 

‘饭后’甜点

  1. 可否以字符串常量作为锁定的对象——不可以

    
    public class SyncTest2 {
    
        String s1 = "hello";
        String s2 = "hello";
    
        public void test1() {
            synchronized (s1) {
                System.out.println("t1 start...");
                try {
                    for (int i=1;i<5;i++){
                        TimeUnit.SECONDS.sleep(i);
                        System.out.println("t1 sleep "+ i);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t1 end...");
            }
        }
    
        public void test2() {
            synchronized (s2) {
                System.out.println("t2 start...");
                System.out.println("t2 end...");
            }
        }
    
        public static void main(String[] args) {
            SyncTest2 demo = new SyncTest2();
            new Thread(demo::test1, "test1").start();
            new Thread(demo::test2, "test2").start();
        }
    }
    

  2. 一个同步方法调用另外一个同步方法,能否得到锁?(重入锁的另外一种情况(继承))———可以

    
    public class SyncTest3 {
    
        synchronized void test1(){
            System.out.println("t1 start");
            try {
                for (int i=1;i<5;i++){
                    TimeUnit.SECONDS.sleep(i);
                    System.out.println("t1 sleep "+ i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            test2();
            System.out.println("t1 end");
        }
    
        synchronized void test2(){
            System.out.println("t2 start");
            System.out.println("t2 end");
        }
    
        public static void main(String[] args) {
            SyncTest3 syncTest3=new SyncTest3();
            syncTest3.test1();
        }
    }
    

  3. 同步方法和非同步方法是否可以同时调用?——可以

    
    public class SyncTest4 {
    
        public synchronized void test1() {
            System.out.println("t1 start");
            try {
                for (int i=1;i<5;i++){
                    TimeUnit.SECONDS.sleep(i);
                    System.out.println("t1 sleep "+ i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("t1 end");
        }
    
        public void test2() {
            System.out.println("t2 start");
            System.out.println("t2 end");
        }
    
        public static void main(String[] args) {
            SyncTest4 demo = new SyncTest4();
            new Thread(demo::test1).start();
            new Thread(demo::test2).start();
        }
    }
    


Ending~

这只是synchronized初步应用,接下来我们将要一层层刨根问底儿~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值