2。线程相关的关键词(synchronized,volatile,ThreadLocal)

1、synchronized

synchronized分类锁和对象锁;

package com.study.syn;

/**
 * Created by Administrator on 2019/7/28.
 */
public class SynTest {

    public synchronized void syn1(){
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("syn1....................."+ Thread.currentThread().getName());
    }

    public static synchronized void synStatic(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("syn static.....................");
    }

}

代码中syn1就是属于对象锁,另外方法中的synchronized 代码块也是属于对象锁,而静态变量修饰的synStatic就是属于类锁;

对象锁 锁的是该类SynTest的实例对象;

类锁 锁的是SynTest的类对象;当使用Spring管理bean时,一般都是注入的单例bean,通常来说就是锁的SynTest这个单实例;

测试对象锁:

1、新建个线程类

package com.study.syn;

/**
 * Created by Administrator on 2019/7/28.
 */
public class Threads extends Thread{

    SynTest synTest;
    public Threads(SynTest synTest){
        this.synTest = synTest;
    }

    @Override
    public void run() {
        synTest.syn1();
    }
}

2、main方法来测试这个对象锁;

package com.study.syn;

/**
 * Created by Administrator on 2019/7/28.
 */
public class Test {

    public static void main(String[] args) {
         SynTest synTest1 = new SynTest();
        //SynTest synTest2 = new SynTest();
        //SynTest synTest3 = new SynTest();
        //SynTest synTest4 = new SynTest();

        Threads t1 = new Threads(synTest1);
        Threads t2 = new Threads(synTest1);
        Threads t3 = new Threads(synTest1);
        Threads t4 = new Threads(synTest1);

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

3、执行main方法后,运行结果:

每隔两秒打印

syn1.....................Thread-0
syn1.....................Thread-3
syn1.....................Thread-2
syn1.....................Thread-1

结果:说明:syn1方法是被锁住了的,4个线程访问syn1方法,只能依次等待锁放开;此处是竞争的synTest1这个实例对象;

4、测试类的多个实例对象

package com.study.syn;

/**
 * Created by Administrator on 2019/7/28.
 */
public class Test {

    public static void main(String[] args) {
        SynTest synTest1 = new SynTest();
        SynTest synTest2 = new SynTest();
        SynTest synTest3 = new SynTest();
        SynTest synTest4 = new SynTest();

        Threads t1 = new Threads(synTest1);
        Threads t2 = new Threads(synTest2);
        Threads t3 = new Threads(synTest3);
        Threads t4 = new Threads(synTest4);

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

此处意思是4个线程去跑4个对象实例,这样的结果就是在2秒后相继打印出

syn1.....................Thread-1
syn1.....................Thread-0
syn1.....................Thread-2
syn1.....................Thread-3

说明这4个线程竞争的不是一个锁,如果说是竞争的一个锁的话,打印的结果应该是每隔2秒打印一个输出;

测试类锁:

1、把Threads线程类中的run方法中的调用方法改为 :synTest.synStatic();运行测试对象锁的2种main;2种测试结果是一致的,都是在一秒后输出一条打印信息,说明2种方式竞争的锁都是同一个锁;

以上就是对象锁的解释,个人记录------------------------分割线----------------------------

2、volatile

volatile关键字:个人感觉不好解释(其实解释不来),只知道这个用处是什么,变量被volatile修饰后,每次要访问这个被修饰的变量时,都是通过去内存读取该变量,在读取方面来说是比较安全的(前提是一个线程去写,其他的线程去读);volatile是非线程安全的,即当多个线程去修改该变量时,可能会存在错误,不会像Atomic包下面的CAS方式,修改值时去compare;说了这么多,代码测试

package com.study.volatiles;

/**
 * Created by Administrator on 2019/7/28.
 */
public class ThreadVolatile implements Runnable{

    private volatile int anInt = 0;

    @Override
    public void run() {
        try {
            System.out.println("线程名字:"+Thread.currentThread().getName()+"---执行加的操作:加之前的值"+anInt);
            anInt = anInt + 2;
            Thread.sleep(100);
            System.out.println("线程名字:"+Thread.currentThread().getName()+"---执行加的操作:加之后的值为"+anInt);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

通过ThreadVolatile 的一个实例对象来创建多个线程

package com.study.volatiles;

/**
 * Created by Administrator on 2019/7/28.
 */
public class VolatileTest {

    public static void main(String[] args) {
        ThreadVolatile threadVolatile = new ThreadVolatile();
        Thread thread1 = new Thread(threadVolatile);
        Thread thread2 = new Thread(threadVolatile);
        Thread thread3 = new Thread(threadVolatile);
        Thread thread4 = new Thread(threadVolatile);

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


}

如果说volatile 修饰的anInt是原子性的,那么每个线程对于修改他的前后值应该是只差2的;运行结果就证实是非原子性的,即volatile修饰的变量时非线程安全的;

volatile适用的地方:一个线程去写修饰的变量,其他的线程去读这个变量:那么是属于可行的;

3、ThreadLocal

ThreadLocal是属于线程级变量;相当于使用ThreadLocal来创建的变量,比如一个实现runable的类的实例,被创建了5个线程,这五个线程中访问的是一个类实例中的变量a,但是ThreadLocal方式就会使这5个线程各自拥有一个独立的线程变量a,他们的取值,赋值都是独立的,都不会有影响,查阅网上有句话说的是:ThreadLocal是以空间换时间,每个线程创建一个副本,来达到同时访问,而互不冲突;synchronized是以时间换空间,线程获取锁(等待执行),达到线程安全;

以上通过学习后,纯手码,有人看到不对可直接开喷,越喷越进步,继续努力。。。。。。。。。。。。。。。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值