对象锁
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只能修于变量。
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();
}
}