一. 线程安全
线程安全问题是指程序中公用的东西被多个线程訪问,比方:类的静态变量
线程互斥:是指两个线程之间不能够同一时候执行,他们会互斥,必须等待一个线程执行完成,还有一个才干执行
二. 同步锁
有什么办法能够解决线程安全问题呢?那就是在程序中加锁
Java有两种加锁的方法:
1. 在代码块中加锁 synchronized (this) { ... }
2. 在方法上加锁 public synchronized void xxx(){ ... }
演示样例代码:
public class TraditionalThreadSynchronized { public static void main(String[] args) { new TraditionalThreadSynchronized().init(); } private void init() { final Outputer outputer = new Outputer(); // 线程1 new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(10); outputer.output1("1111111111"); } catch (Exception e) { e.printStackTrace(); } } } }).start(); // 线程2 new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(10); outputer.output1("2222222222"); } catch (Exception e) { e.printStackTrace(); } } } }).start(); } class Outputer { public void output1(String name) { // 同步代码块 synchronized (this) { for (int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); } System.out.println(); } } // 同步方法 public synchronized void output2(String name) { for (int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); } System.out.println(); } } }
线程1和线程2由于都要调用output1方法并打印传入的name字符串。cpu就会来回的在两个线程之间切换,
有可能线程1打印到一半的时候就切换到线程2上。这显然是我们不想看到的,所以在代码内容中加锁,
这样能够保证一个线程调用方法结束才会运行下一个线程。
上面代码中的this指的是outputer对象,它就是一把锁,两个线程使用同一把锁才干实现同步。
而在方法上加锁也能够实现线程同步,在方法上使用synchronizedkeyword也是把this作为锁。
事实上output1方法和output2方法也是同步的,由于他们都是使用this作为锁。
思考一个问题:假设把一个方法定义为静态的即:public static synchronized
那么它使用什么作为锁呢?答案是:该类的字节码对象xxx.class
三. Synchonized和ThreadLocal
ThreadLocal和Synchonized都用于解决多线程并发訪问,可是它们之间有本质差别,synchonized是利用锁机制,使变量或代码块在某一时刻仅仅能被一个线程訪问,而ThreadLocal为每个线程提供一个变量副本,每个线程在同一时间訪问到的并非同一个对象,这样就隔离了多个线程对数据的共享,而Synchronized却正好相反。它用于在多个线程间通信时可以获得数据共享。
总结:synchonized用于线程间数据共享。ThreadLocal用于线程间数据隔离。
版权声明:本文博主原创文章,博客,未经同意不得转载。