精通Java多线程学习(四)synchronized关键字的使用

前面的章节介绍到,当有两个线程去操作一个数据时,会出现安全隐患。在这一节中我们将来解决这个问题。

需要用到线程的同步。即synchronized关键字。


使用synchronized关键字有两个前提:

1.有两个以上的线程。

2.使用同一个锁。


1.同步代码块

下面针对前面的问题对代码进行一些改进,加入同步代码块。

public class RunnableDemo1 implements Runnable{
    private int i;
    Object obj = new Object();
    @Override
    public void run() {
        synchronized (obj){
            while (i<600){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"实现Runnable接口的线程类运行:"+i++);
            }
        }

    }
}

同步的代码块必须要有一个锁,这里使用的是obj这个对象。

再次运行测试代码就可以看见程序正确的输出了。


2.同步方法

synchronized关键字用在方法上也是同样的效果。同步方法使用的锁是this。

下面是使用同步方法实现的解决方案

public class RunnableDemo1 implements Runnable{
    private int i;
    @Override
    public void run() {
            while (i<600){
                print();
            }

    }
    public synchronized void print(){
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"实现Runnable接口的线程类运行:"+i++);
    }
}

3.类锁(static修饰的共享数据)

当共享数据被static关键字修饰时这时我们这个类的所有实例共享这个数据。

将i改写成类变量

public class RunnableDemo1 implements Runnable{
    private static int i;
    Object obj = new Object();
    @Override
    public void run() {
            while (i<600){
                synchronized (obj){
                    //print();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"实现Runnable接口的线程类运行:"+i++);
                }

            }

    }
}
编写测试类:
public class Test {
    public static void main(String[] args){
       RunnableDemo1 demo1 = new RunnableDemo1();
        RunnableDemo1 demo2 = new RunnableDemo1();
       Thread t1 = new Thread(demo1);
        Thread t2 = new Thread(demo2);

        t1.start();
        t2.start();
    }
}

这里是使用两个实例来开启的两个线程。而锁还是一个简单的对象锁。

运行程序。


可以看到出现了大量的重复数据。

这是因为我们操作的是类变量,这里需要使用类锁。

只需将同步的锁由obj改成当前的Class即可


再次运行程序。程序正常输出。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值