1.ThreadLocal用法
在java中,如果一个变量需要被多个线程访问,可以使用volatile来声明它为“易变的”。而假如一个变量要被持有它的某个线程独享,在java中,它可以使用java.lang.ThreadLocal类来实现线程本地存储的功能。这样,数据便只在同一个线程内可见和共享,因此,即便不同步也能保证线程之间不出现数据争用。
ThreadLocal使得各线程能够保持各自独立的一个对象,通过ThreadLocal.set()来设置对象的值,保存在每个线程自己都有的一个map对象当中,每个ThreadLocal对象会有一个线程范围内唯一hashcode作为key,ThreadLocal.get()内部通过这个key从map中取值,因此取出来的是各自自己线程中的对象,ThreadLocal实例事实上只是作为map的key来使用的
ThreadLocal例子
package com.arch.demo;
public class ThreadLocalTest {
public static void main(String[] args) {
ThreadLocal<Integer> count = new ThreadLocal<>();
ConcurrentThread t1 = new ConcurrentThread(count);
ConcurrentThread t2 = new ConcurrentThread(count);
ConcurrentThread t3 = new ConcurrentThread(count);
ConcurrentThread t4 = new ConcurrentThread(count);
t1.start();
t2.start();
t3.start();
t4.start();
}
static class ConcurrentThread extends Thread {
ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
private ConcurrentThread(ThreadLocal<Integer> count) {
this.threadLocal = count;
}
@Override
public void run() {
for (int i = 1; i < 10; i++) {
if (threadLocal.get() != null) {
threadLocal.set(threadLocal.get() + 1);
} else {
threadLocal.set(1);
}
System.out.println("Thread:" + this.currentThread().getName() + ",Count:" + threadLocal.get());
}
}
}
}
2.volatile用法
volatile是轻量级的synchronized, 它在多处理器开发中保证了共享变量的"可见性", 可见性是指一个线程在修改共享变量的值时,其他的线程可以读到这个修改的值
3.Synchronized与ReentranckLock区别
- Lock和 synchronized 有一点明显的区别 —— lock 必须在 finally 块中释放
2. Lock可以实现公平锁或不公平锁,而Synchronized是不公平的,而且永远都是不公平的。但 JVM 保证了所有线程最终都会得到它们所等候的锁,但是Lock作为默认设置,把公平设置为false
3. Lock性能和伸缩性都比较好(在JDK5.0),但是大多数情况Synchronized就足够了,而且更容易理解
4.ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”。也就是说ReentrantLock在同一个时间点只能被一个线程获取
4. 重要点
1).当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块
public class SynchronizedThread implements Runnable {
@Override
public void run() {
synchronized (this){
for(int i = 0; i < 5; i++){
System.out.println(Thread.currentThread().getName() + " synchronized loop" + i);
}
}
}
public static void main(String[] args) {
Runnable runnable = new SynchronizedThread();
new Thread(runnable,"a").start();
new Thread(runnable,"b").start();
}
}
2).当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块