Synchronized关键字踩坑

在java中开启线程有4种方式,分别是

(1)继承Thread类创建线程

(2)实现Runnable接口创建线程

(3)使用Callable和Future创建线程

(4)使用线程池例如用Executor框架

作为新手,我最近着重复习了前两种方法,通过实际操作可以感受到其不同之处。

Runnable
设置类X实现了runnable接口,重写其中的run方法(加上sychronized关键字),并在main函数中创建X的实例对象that,用that开启2个线程。

package JavaTutorial;

import static java.lang.Thread.sleep;

public class SychronizedLock {

public static void main(String[] args) {

    X that = new X();
    (new Thread(that)).start();
    (new Thread(that)).start();

}

}
class X implements Runnable{

private int x;
private int y;
@Override
public synchronized void run() {
    for (;;){
        x++;
        y++;
        System.out.println("x="+x+",y="+y);
        try {
            sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}
得到结果如下
Synchronized关键字踩坑_第1张图片

可见,加上synchronized关键字之后,只有第一个子线程在执行。 这里的public synchronized void run() 等于public synchronized void run(this) 即,对run方法加上了同步锁。 如果把sychronized关键字删除,则有结果
Synchronized关键字踩坑_第2张图片

res2 可见2个线程同时进行。 以上是实现runnable接口的情况。

题外话说一句:在事务中,通常需要对一个类或一个对象之加上同步锁 如:sychronized(obj),sychronizd(obj.class) 这样可以避免多个线程同时访问改对象/类的情况发生。

Thread
当使用extends Thread实现多线程的时候,若直接使用调用start方法,同样可以开启多线程。 如:

public static void main(String[] args) {
    new Thread().start();
    new Thread().start();
}

同样为run方法加上sychronized关键字,此时两个子线程都会执行。 这是因为生成了2个线程对象,所以这2个线程对象都拿到各自对象的该锁! 我们在写runnable的时候就没有这个问题,因为我们用的是同一个X对象。

你可能感兴趣的:(JAVA,thread)