java——synchronized关键字(1)

 

 

一句话形容Synchronized关键字的作用:能够保证同一时刻,最多只有一个线程执行该段代码,已达到并发安全的效果。

一、对象锁

1、代码块:

package com.example.springwebfluxtest.synchronize;

public class SynchronizedObjectCodeBlock2 implements Runnable {
    static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();

    @Override
    public void run() {
        synchronized (this){
            System.out.println("我是对象锁的代码块形式"+"我叫"+Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"运行结束");
        }

    }

    public static void main(String[] args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }
}

运行结果:(保证串行执行)

我是对象锁的代码块形式我叫Thread-1
Thread-1运行结束
我是对象锁的代码块形式我叫Thread-0
Thread-0运行结束
finished

 

package com.example.springwebfluxtest.synchronize;

public class SynchronizedObjectCodeBlock2 implements Runnable {
    static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
    Object lock1 = new Object();
    Object lock2 = new Object();
    @Override
    public void run() {
        synchronized (lock1){
            System.out.println("我是lock1"+"我叫"+Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"lock1运行结束");
        }
        synchronized (lock2){
            System.out.println("我是lock2"+"我叫"+Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"lock2运行结束");
        }

    }

    public static void main(String[] args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }
}

运行结果:
我是lock2我叫Thread-0        几乎同时
我是lock1我叫Thread-1

我是lock1我叫Thread-0
Thread-0lock1运行结束
我是lock2我叫Thread-0
我是lock1我叫Thread-1
Thread-0lock2运行结束
Thread-1lock1运行结束
我是lock2我叫Thread-1
Thread-1lock2运行结束
finished

调试技巧:

切换线程

2、普通方法:

package com.example.springwebfluxtest.synchronize;

public class SynchronizedObjectMehod3 implements Runnable {
    static SynchronizedObjectMehod3 instance = new SynchronizedObjectMehod3();

    public static void main(String[] args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }
    @Override
    public void run() {
        method();
    }
    public synchronized void method(){
        System.out.println("我是对象锁的方法修饰符形式"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
}

运行结果:

我是对象锁的方法修饰符形式我叫Thread-1
Thread-1运行结束
我是对象锁的方法修饰符形式我叫Thread-0
Thread-0运行结束
finished

二、类锁

1、synchronized加在static方法上

package com.example.springwebfluxtest.synchronize;

public class SynchronizedClassStatic4 implements Runnable {
    static SynchronizedClassStatic4 instance1 = new SynchronizedClassStatic4();
    static SynchronizedClassStatic4 instance2 = new SynchronizedClassStatic4();
    @Override
    public void run() {
        method();
    }
    public static synchronized void method(){
        System.out.println("我是类锁的静态方法"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instance1);
        Thread t2 = new Thread(instance2);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }
}

运行结果:

我是类锁的静态方法我叫Thread-1
Thread-1运行结束
我是类锁的静态方法我叫Thread-0
Thread-0运行结束
finished

2、synchronized(*。class)代码块

package com.example.springwebfluxtest.synchronize;

public class SynchronizedClassClass implements Runnable {
    static SynchronizedClassClass instance1 = new SynchronizedClassClass();
    static SynchronizedClassClass instance2 = new SynchronizedClassClass();
    @Override
    public void run() {
        method();
    }
    public void method(){
        synchronized(SynchronizedClassClass.class){
            System.out.println("我是类锁*.class"+"我叫"+Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"运行结束");
        }

    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instance1);
        Thread t2 = new Thread(instance2);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }
}

运行结果:

我是类锁*.class我叫Thread-1
Thread-1运行结束
我是类锁*.class我叫Thread-0
Thread-0运行结束
finished

多线程访问同步方法的7种情况

4、同时访问同步与非同步方法:非同步方法不受到影响:

package com.example.springwebfluxtest.synchronize;

public class SynchronizedYesAndNo6 implements Runnable {
    static SynchronizedYesAndNo6 instance  = new SynchronizedYesAndNo6();
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            method();
        }else{
            method2();
        }

    }
    public synchronized void method(){
        System.out.println("我是同步方法"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public void method2(){
        System.out.println("我是非同步方法"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }

}

运行结果:

我是非同步方法我叫Thread-1
我是同步方法我叫Thread-0
Thread-0运行结束
Thread-1运行结束
finished

package com.example.springwebfluxtest.synchronize;

public class SynchronizedDifferentMethod7 implements Runnable {
    static SynchronizedDifferentMethod7 instance  = new SynchronizedDifferentMethod7();
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            method();
        }else{
            method2();
        }

    }
    public synchronized void method(){
        System.out.println("我是同步方法1"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public synchronized void method2(){
        System.out.println("我是同步方法2"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }

}

运行结果:

我是同步方法1我叫Thread-0
Thread-0运行结束
我是同步方法2我叫Thread-1
Thread-1运行结束
finished

package com.example.springwebfluxtest.synchronize;

public class SynchronizedStaticAndNormal8 implements Runnable {
    static SynchronizedStaticAndNormal8 instance  = new SynchronizedStaticAndNormal8();
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            method();
        }else{
            method2();
        }

    }
    public synchronized static void method(){
        System.out.println("我是static同步方法1"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public synchronized void method2(){
        System.out.println("我非static是同步方法2"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }

}

运行结果:

我非static是同步方法2我叫Thread-1
我是static同步方法1我叫Thread-0
Thread-1运行结束
Thread-0运行结束
finished

package com.example.springwebfluxtest.synchronize;

public class SynchronizedException9 implements Runnable {
    static SynchronizedException9 instance  = new SynchronizedException9();
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")){
            method();
        }else{
            method2();
        }

    }
    public synchronized  void method(){
        System.out.println("我是同步方法1"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
            throw new Exception();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public synchronized void method2(){
        System.out.println("我是同步方法2"+"我叫"+Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        while(t1.isAlive()||t2.isAlive()){

        }
        System.out.println("finished");
    }

}

运行结果(有问题):

我是同步方法2我叫Thread-1
Thread-1运行结束
我是同步方法1我叫Thread-0
java.lang.Exception
    at com.example.springwebfluxtest.synchronize.SynchronizedException9.method(SynchronizedException9.java:18)
    at com.example.springwebfluxtest.synchronize.SynchronizedException9.run(SynchronizedException9.java:8)
    at java.lang.Thread.run(Thread.java:748)
Thread-0运行结束
finished

视频的结果:

核心思想:

目前我进入到了一个被synchronized修饰的方法,而在这个方法里调用了另外一个没有被synchronized修饰的方法,这个时候线程不是安全的。

synchronized的性质:

1、可重入

情况1:

package com.example.springwebfluxtest.synchronize;

/**
 * 可重入粒度测试:递归调用本方法
 */
public class SynchronizedRecursion9 {
     int a = 0;
    public static void main(String[] args) {
        SynchronizedRecursion9 synchronizedRecursion9 = new SynchronizedRecursion9();
        synchronizedRecursion9.method1();
    }
    private synchronized void method1(){
        System.out.println("这是method1,a="+a);
        if(a == 0){
            a++;
            method1();
        }
    }
}

运行结果:

这是method1,a=0
这是method1,a=1

情况2:

package com.example.springwebfluxtest.synchronize;

/**
 * 可重入粒度测试2:调用类内部其他的方法
 */
public class SynchronizedRecursion11 {
    public static void main(String[] args) {
        SynchronizedRecursion11 synchronizedRecursion9 = new SynchronizedRecursion11();
        synchronizedRecursion9.method1();
    }
    public synchronized void method1(){
        System.out.println("我是mthod1()");
        method2();
    }
    private synchronized void method2(){
        System.out.println("我是method2");
    }
}

运行结果:

我是mthod1()
我是method2

情况3:

结果

我是子类方法
我是父类方法

package com.example.springwebfluxtest.synchronize;

import javax.xml.bind.SchemaOutputResolver;

/**
 * 可重入粒度测试3:调用父类方法
 */
public class SynchronizedRecursion12 {
   public synchronized void doSomething(){
       System.out.println("我是父类方法");
   }
}
class TestClass extends SynchronizedRecursion12{
    public synchronized void doSomething(){
        System.out.println("我是子类方法");
        super.doSomething();
    }

    public static void main(String[] args) {
        TestClass testClass = new TestClass();
        testClass.doSomething();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值