Java中线程基础-线程间的共享-volatile

对象锁 

package com.xiangxue.ch1.syn;

import com.xiangxue.tools.SleepTools;

/**
 *
 *类说明:演示对象锁和类锁
 */
public class SynClzAndInst {
	
	//使用类锁的线程
    private static class SynClass extends Thread{
        @Override
        public void run() {
            System.out.println("TestClass is running...");
            synClass();
        }
    }

  //使用对象锁的线程1
    private static class InstanceSyn implements Runnable{
        private SynClzAndInst synClzAndInst;

        public InstanceSyn(SynClzAndInst synClzAndInst) {
            this.synClzAndInst = synClzAndInst;
        }

        @Override
        public void run() {
            System.out.println("TestInstance is running..."+synClzAndInst);
            synClzAndInst.instance();
        }
    }

  //使用对象锁的线程2
    private static class Instance2Syn implements Runnable{
        private SynClzAndInst synClzAndInst;

        public Instance2Syn(SynClzAndInst synClzAndInst) {
            this.synClzAndInst = synClzAndInst;
        }
        @Override
        public void run() {
            System.out.println("TestInstance2 is running..."+synClzAndInst);
            synClzAndInst.instance2();
        }
    }

    //锁对象
    private synchronized void instance(){
        SleepTools.second(3);
        System.out.println("synInstance is going..."+this.toString());
        SleepTools.second(3);
        System.out.println("synInstance ended "+this.toString());
    }
    
    //锁对象
    private synchronized void instance2(){
        SleepTools.second(3);
        System.out.println("synInstance2 is going..."+this.toString());
        SleepTools.second(3);
        System.out.println("synInstance2 ended "+this.toString());
    }

    //类锁,实际是锁类的class对象
    private static synchronized void synClass(){
        SleepTools.second(1);
        System.out.println("synClass going...");
        SleepTools.second(1);
        System.out.println("synClass end");
    }

    public static void main(String[] args) {
    	SynClzAndInst synClzAndInst = new SynClzAndInst(); //按顺序先new外部类
    	Thread t1 = new Thread(new InstanceSyn(synClzAndInst)); //内部类以外部类作成员变量
    	
    	//SynClzAndInst synClzAndInst2 = new SynClzAndInst();
    	Thread t2 = new Thread(new Instance2Syn(synClzAndInst)); //Instance2Syn实现了Runnable接口
    	
    	t1.start();
    	t2.start();
    	
//    	SynClass synClass = new SynClass();
//    	synClass.start();
    	SleepTools.second(1);
    }
}

工具类

package com.xiangxue.tools;

import java.util.concurrent.TimeUnit;

/**
 * 
 *
 *类说明:线程休眠辅助工具类
 */
public class SleepTools {
	
	/**
	 * 按秒休眠
	 * @param seconds 秒数
	 */
    public static final void second(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
        }
    }
    
    /**
     * 按毫秒数休眠
     * @param seconds 毫秒数
     */
    public static final void ms(int seconds) {
        try {
            TimeUnit.MILLISECONDS.sleep(seconds);
        } catch (InterruptedException e) {
        }
    }
}

执行结果

线程间的共享

synchronized

对象锁,锁的是类的对象实例。

类锁 ,锁的是每个类的的Class对象,每个类的的Class对象在一个虚拟机中只有一个,所以类锁也只有一个。

执行结果

volatile关键字

volatile可以保证数据在多个线程之间可见性,但不可以保证原子性。适合于只有一个线程写,多个线程读的场景。

关键字volatile是线程同步的轻量级实现,性能比synchronized要好,并且volatile只能修于变量。

volatile关键字可以实现禁止指令的重排序优化。

package com.xiangxue.ch1.vola;

import com.xiangxue.tools.SleepTools;

/**
 *
 *类说明:演示violate无法提供操作的原子性
 */
public class VolatileUnsafe {
	
	private static class VolatileVar implements Runnable {

		private volatile int a = 0;
		
	    @Override
	    public void run() {
	    	String threadName = Thread.currentThread().getName();
	    	a = a++;
	    	System.out.println(threadName+":======"+a);
	    	SleepTools.ms(100);
	    	a = a+1;
	    	System.out.println(threadName+":======"+a);
	    }
	}
	
    public static void main(String[] args) {

    	VolatileVar v = new VolatileVar();

        Thread t1 = new Thread(v);
        Thread t2 = new Thread(v);
        Thread t3 = new Thread(v);
        Thread t4 = new Thread(v);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }

}

ThreadLocal

线程变量。可以理解为是个map,类型 Map<Thread,Integer>

package com.xiangxue.ch1;

/**
 *
 *类说明:演示ThreadLocal的使用
 */
public class UseThreadLocal {
	
	//可以理解为 一个map,类型 Map<Thread,Integer>
	static ThreadLocal<Integer> threadLaocl = new ThreadLocal<Integer>(){
		@Override
		protected Integer initialValue() {
			return 1;
		}
	};

    /**
     * 运行3个线程
     */
    public void StartThreadArray(){
        Thread[] runs = new Thread[3]; //数组一种3个元素
        for(int i=0;i<runs.length;i++){
            runs[i]=new Thread(new TestThread(i));
        }
        for(int i=0;i<runs.length;i++){
            runs[i].start();
        }
    }
    
    /**
     *类说明:测试线程,线程的工作是将ThreadLocal变量的值变化,并写回,看看线程之间是否会互相影响
     */
    public static class TestThread implements Runnable{
        int id;
        public TestThread(int id){
            this.id = id;
        }
        public void run() {
            System.out.println(Thread.currentThread().getName()+":start");
            Integer s = threadLaocl.get();//获得变量的值
            s = s+id;
            threadLaocl.set(s);
            System.out.println(Thread.currentThread().getName()+":"
            +threadLaocl.get());
            //threadLaocl.remove();
        }
    }

    public static void main(String[] args){
    	UseThreadLocal test = new UseThreadLocal();
        test.StartThreadArray();
    }
}

发布了132 篇原创文章 · 获赞 21 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_40993412/article/details/104144378