如何保证线程安全
1、同步代码块。
synchronized(共享资源对象){//对共享资源对象加锁
//代码(原子操作)
}
注:
每个对象都有一个互斥锁标记,用来分配给线程的。
只有拥有对象互斥锁标记的线程,才可以进入该对象加锁的同步代码块。
线程退出同步代码块时,会释放相应的互斥锁标记。
代码示例:
//当前数组下标值 private static int INDEX = 0; public static void main(String[] args) throws InterruptedException { //定义一个长度为5的数组 String[] arr = new String[5]; //定义两个线程,分别往数组中插入不同的值。 //这里我们期望可以得到["ONE","TWO",null.null,null] Thread t1 = new Thread(() -> { synchronized (arr) { arr[INDEX] = "ONE"; INDEX++; } }); Thread t2 = new Thread(() -> { synchronized (arr) { arr[INDEX] = "TWO"; INDEX++; } }); //启动线程 t1.start(); t2.start(); //这里为了保证输出时这两个线程已经执行完毕,使用join方法来阻塞主线程 t1.join(); t2.join(); //打印数据数据 System.out.println(Arrays.toString(arr)); }
这时的结果无论执行多少次都不会出现元素覆盖的情况,结果为[ONE, TWO, null, null, null]或[TWO, ONE, null, null, null]。因为没有去控制线程执行顺序。
2、同步方法。
synchronized 返回值类型 方法名称(形参列表){//对当前对象this加锁
//代码(原子操作)
}
注:
只有拥有该对象互斥锁标记的线程才能进入该对象加锁的同步方法中。
线程退出同步方法时,会释放拥有的互斥锁标记。
代码示例:
//假设有三个售票窗口,总共销售100张票 private static int TICKET = 100; public static void main(String[] args) { //定义售票窗口,执行售票方法 Thread t1 = new Thread(() -> { while (true) { if (!sale()) { break; } } }, "t1"); Thread t2 = new Thread(() -> { while (true) { if (!sale()) { break; } } }, "t2"); Thread t3 = new Thread(() -> { while (true) { if (!sale()) { break; } } }, "t3"); //启动三个线程,开始卖票 t1.start(); t2.start(); t3.start(); } /** * 静态方法,锁的是当前方法所在的类 * 非静态方法,锁的是this,调用该方法的对象。 * @return */ private synchronized static boolean sale() { if (TICKET <= 0) { return false; } System.out.println(Thread.currentThread().getName() + "销售了第" + TICKET + "张票"); TICKET--; return true; }
输出结果:
t1销售了第100张票 t1销售了第99张票 t1销售了第98张票 t1销售了第97张票 t1销售了第96张票 t1销售了第95张票 t1销售了第94张票 t1销售了第93张票 t2销售了第92张票 t2销售了第91张票 t2销售了第90张票 t2销售了第89张票 t2销售了第88张票 t2销售了第87张票 t2销售了第86张票 t2销售了第85张票 t2销售了第84张票 t2销售了第83张票 t2销售了第82张票 t2销售了第81张票 t2销售了第80张票 t2销售了第79张票 t2销售了第78张票 t2销售了第77张票 t2销售了第76张票 t2销售了第75张票 t2销售了第74张票 t2销售了第73张票 t2销售了第72张票 t2销售了第71张票 t2销售了第70张票 t2销售了第69张票 t2销售了第68张票 t2销售了第67张票 t2销售了第66张票 t2销售了第65张票 t2销售了第64张票 t2销售了第63张票 t2销售了第62张票 t2销售了第61张票 t2销售了第60张票 t2销售了第59张票 t2销售了第58张票 t2销售了第57张票 t2销售了第56张票 t2销售了第55张票 t2销售了第54张票 t2销售了第53张票 t2销售了第52张票 t2销售了第51张票 t2销售了第50张票 t2销售了第49张票 t2销售了第48张票 t2销售了第47张票 t2销售了第46张票 t2销售了第45张票 t2销售了第44张票 t2销售了第43张票 t2销售了第42张票 t2销售了第41张票 t2销售了第40张票 t2销售了第39张票 t2销售了第38张票 t2销售了第37张票 t2销售了第36张票 t2销售了第35张票 t2销售了第34张票 t2销售了第33张票 t2销售了第32张票 t2销售了第31张票 t2销售了第30张票 t2销售了第29张票 t2销售了第28张票 t2销售了第27张票 t2销售了第26张票 t2销售了第25张票 t2销售了第24张票 t2销售了第23张票 t2销售了第22张票 t2销售了第21张票 t2销售了第20张票 t2销售了第19张票 t2销售了第18张票 t2销售了第17张票 t2销售了第16张票 t2销售了第15张票 t2销售了第14张票 t2销售了第13张票 t2销售了第12张票 t2销售了第11张票 t2销售了第10张票 t2销售了第9张票 t2销售了第8张票 t2销售了第7张票 t2销售了第6张票 t2销售了第5张票 t2销售了第4张票 t2销售了第3张票 t2销售了第2张票 t3销售了第1张票 Process finished with exit code 0

浙公网安备 33010602011771号