synchronized使用

一、synchronized加锁方式

 synchronized可以使多线程同步运行。

synchronized的使用时需要配合对象,即每一个synchronized修饰的方法或代码块都会配备一个对象,这个对象可以是实例对象也可以是类对象,类锁本质上也是Class类的实例对象。所以每一个synchronized都会跟一个实例对象对应。

synchronized修饰方法时,默认加的是当前对象实例的锁;修饰静态方法时默认加的是当前类的类对象的锁。修饰代码块和静态代码块,书写方式一样,不同的是所加的对象锁。

互斥规则:

1、当一个线程访问某对象的synchronized方法或代码块时,其他线程可以访问非synchronized方法或代码块,不会阻塞。

2、当锁是同一对象实例时,一个线程访问该对象的synchronized方法或代码块时,其他线程访问该对象的synchronized方法或代码块时,会被阻塞。

3、同一类的不同实例对象的对象锁互不干扰。

4、类锁也是一种特殊的对象锁,第2条同样适用,适用于静态方法和加了类锁的代码块。

5、类锁和对象锁互不干扰。

二、加锁实例

import lombok.SneakyThrows;

public class SynchThread implements Runnable {
    @SneakyThrows
    @Override
    public void run() {
        if("static_method".equals(Thread.currentThread().getName())){
            synchronizedStaticMethod();
        }else if("no_static_method".equals(Thread.currentThread().getName())){
            synchronizedMethod();
        }else if ("static_block".equals(Thread.currentThread().getName())){
            synchronized(SynchThread.class){
                System.out.println(Thread.currentThread().getName()+" :synchronized静态代码块start.....");
                System.out.println(Thread.currentThread().getName()+" :synchronized静态代码块sleep.....");
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName()+" :synchronized静态代码块voer!!!");
            }
        }else if ("no_static_block".equals(Thread.currentThread().getName())){
            synchronized (this){
                System.out.println(Thread.currentThread().getName()+" :synchronized代码块start.....");
                System.out.println(Thread.currentThread().getName()+" :synchronized代码块sleep.....");
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName()+" :synchronized代码块voer!!!");
            }
        }


    }


    @SneakyThrows
    public synchronized void synchronizedMethod(){
        System.out.println(Thread.currentThread().getName()+" :synchronized方法start....");
        System.out.println(Thread.currentThread().getName()+" :synchronized方法sleep....");
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName()+" :synchronized方法voer!!!");
    }

    @SneakyThrows
    public synchronized static void synchronizedStaticMethod(){
        System.out.println(Thread.currentThread().getName()+" :synchronized静态方法start....");
        System.out.println(Thread.currentThread().getName()+" :synchronized静态方法sleep....");
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName()+" :synchronized静态方法voer!!!");
    }
}

测试代码:

public class SynchThreadDome {
    public static void main(String[] args){
        Runnable synchRun = new SynchThread();

        Thread thread1 = new Thread(synchRun,"static_method");
        Thread thread2 = new Thread(synchRun,"no_static_method");
        Thread thread3 = new Thread(synchRun,"static_block");
        Thread thread4 = new Thread(synchRun,"no_static_block");

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

    }
}

结果:

static_method :synchronized静态方法start....
static_method :synchronized静态方法sleep....
no_static_method :synchronized方法start....
no_static_method :synchronized方法sleep....
static_method :synchronized静态方法voer!!!
static_block :synchronized静态代码块start.....
static_block :synchronized静态代码块sleep.....
no_static_method :synchronized方法voer!!!
no_static_block :synchronized代码块start.....
no_static_block :synchronized代码块sleep.....
static_block :synchronized静态代码块voer!!!
no_static_block :synchronized代码块voer!!!

上述结果可以看出:

1、静态方法(代码块)和非静态方法(代码块)的执行互不干扰。

2、静态方法和静态代码块之间相互阻塞;非静态方法和非静态代码块之间相互阻塞;

因为静态方法和静态代码块加的是this锁;非静态方法和非静态代码块加的是类锁(SynchThread.class)。

总结:从一个更加广义的角度看待锁的机制,上了同一个锁的多个线程,不管线程调用的是不是同一段逻辑,都会形成阻塞;未上相同锁的多个线程,相互运行不相干。

如下:

package test.thread;

public class TestLock {
    public static void main(String[] args) {
        String str = new String();
        System.out.println("aaa开始");
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                synchronized (str) {
                    for (int i = 0; i < 100; i++) {
                        System.out.println("aaaa"+i);
                    }
                }
            }
        }).start();
        
        System.out.println("bbb开始");
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                synchronized (str) {
                    for (int i = 0; i < 100; i++) {
                        System.out.println("bbbb"+i);
                    }
                }
            }
        }).start();
        
    }
}

以上代码会在aaa0~aaa99输出完成后,在输出bbb0~bbb99.

就算这个世道烂成一堆粪坑,那也不是你吃屎的理由
原文地址:https://www.cnblogs.com/whalesea/p/12970853.html