对kotlin和java中的synchronized的浅谈

回主页

synchronized在java中是一个关键字,但是在kotlin中是一个内联函数。假如分别在java和kotlin代码锁住同一个对象,会发生什么呢,今天写了代码试了试。 首先定义people类

public class People {
    public void doSomething() {
        for (int i = 0; i < 10; i ++) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(String.format("在%s线程中吃第%d个包子", Thread.currentThread().getName(), i));
        }
    }
}

然后定义一个java类开启一个线程并且锁住people

public class MyJavaClass {
    private final People people;

    public MyJavaClass(People people) {
        this.people = people;
    }


    void startThread() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (people) {
                    people.doSomething();
                }
            }
        }, "java").start();
    }
}

再定义一个kotlin类开启一个线程并且锁住相同的people

class MyKotlinClass(private val people: People) {
    fun startThread() {
        Thread(Runnable {
            synchronized(people) {
                people.doSomething()
            }

        }, "kotlin").start()
    }
}

最后在main函数中执行如下代码

fun main(args: Array<String>) {
    val people = People()

    MyJavaClass(people).startThread()
    MyKotlinClass(people).startThread()
}

观察输出结果是:

在java线程中吃第0个包子
在java线程中吃第1个包子
在java线程中吃第2个包子
在java线程中吃第3个包子
在java线程中吃第4个包子
在java线程中吃第5个包子
在java线程中吃第6个包子
在java线程中吃第7个包子
在java线程中吃第8个包子
在java线程中吃第9个包子
在kotlin线程中吃第0个包子
在kotlin线程中吃第1个包子
在kotlin线程中吃第2个包子
在kotlin线程中吃第3个包子
在kotlin线程中吃第4个包子
在kotlin线程中吃第5个包子
在kotlin线程中吃第6个包子
在kotlin线程中吃第7个包子
在kotlin线程中吃第8个包子
在kotlin线程中吃第9个包子

根据结果可以看到java和kotlin在锁住一个对象时可以做到互斥。但是java中的synchronized是个关键字,kotlin中synchronized是个函数,那么它们为什么做到互斥的呢? java中synchronized的底层实现这这篇文章中描述的比较清楚https://blog.csdn.net/hbtj_1216/article/details/77773292,关键字synchronized被编译成了monitorenter和monitorexit。再看kotlin中的synchronized函数

@kotlin.internal.InlineOnly
public inline fun <R> synchronized(lock: Any, block: () -> R): R {
    @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE", "INVISIBLE_MEMBER")
    monitorEnter(lock)
    try {
        return block()
    }
    finally {
        @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE", "INVISIBLE_MEMBER")
        monitorExit(lock)
    }
}

这里边也是有monitorEnter和monitorExit的,所以做出推测,不管synchronized是java中的关键字还是kotlin中的函数,最终被编译成的字节码是一样。

回主页