一、原子性操作
1、ThreadLocal
不同线程操作同一个 ThreadLocal 对象执行各种操作而不会影响其他线程里的值
注意:虽然ThreadLocal
很有用,但是它作为一种线程级别的全局变量,如果某些代码依赖它的话,会造成耦合,从而影响了代码的可重用性
2、变量声明为 final
public class FinalDemo { private final int finalField; public FinalDemo(int finalField) { this.finalField = finalField; } }
3、加锁
在同步代码块中的代码要尽量的短,不要把不需要同步的代码也加入到同步代码块,在同步代码块中千万不要执行特别耗时或者可能发生阻塞的一些操作,比如I/O操作啥的。
某个线程在进入某个同步代码块
的时候去获取一个锁,在退出该代码块的时候把锁给释放掉
public class Increment { private int i; private Object lock = new Object(); public void increase(){ synchronized (lock){ i++; } } public int getI(){ synchronized (lock){ return i; } } public static void test(int threadNum,int loopTimes){ Increment increment = new Increment(); Thread[] threads = new Thread[threadNum]; for(int i = 0; i<threads.length;i++){ Thread t = new Thread(new Runnable() { @Override public void run() { for(int i = 0; i < loopTimes;i++){ increment.increase(); } } }); threads[i] = t; t.start(); } for (Thread t : threads) { //main线程等待其他线程都执行完成 try { t.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } } System.out.println(threadNum + "个线程,循环" + loopTimes + "次结果:" + increment.getI()); } public static void main(String[] args) { test(20, 1); test(20, 10); test(20, 100); test(20, 1000); test(20, 10000); test(20, 100000); } }
二 锁的重入
只要一个线程持有了某个锁,那么它就可以进入任何被这个锁保护的代码块。
ublic class SynchronizedDemo { private Object lock = new Object(); public void m1() { synchronized (lock) { System.out.println("这是第一个方法"); m2(); } } public void m2() { synchronized (lock) { System.out.println("这是第二个方法"); } } public static void main(String[] args) { SynchronizedDemo synchronizedDemo = new SynchronizedDemo(); synchronizedDemo.m1(); } }
三、同步方法
public class Increment { private int i; public void increase() { synchronized (this) { //使用this作为锁 i++; } } public static void anotherStaticMethod() { synchronized (Increment.class) { //使用Class对象作为锁 // 此处填写需要同步的代码块 } } }
可以简写成:
public class Increment { private int i; public synchronized increase() { //使用this作为锁 i++; } public synchronized static void anotherStaticMethod() { //使用Class对象作为锁 // 此处填写需要同步的代码块 } }