我们在开发过程中, 为了提高效率往往都会采用多线程,但是多个线程同时运行的时候可能调用线程函数,在多个线程对同一个内存地址进行修改的时候, 写入数据会被多次的覆盖, 所以就要使用线程同步, 同步就是协同步调, 按照先后顺序进行运行。
那么在 java 中, 我们一般使用同步锁一般采用synchronized实现, 也可以通过Lock实现
package com.cnq.java.thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 确保线程同步
* 第一种方法 : 在subtractCount方法上添加 synchronized -> private synchronized void subtractCount()
* 第二种方法 : 在代码中添加 synchronized 块, synchronized(this){}
* 第三种方法 : 采用 Lock lock=new ReentrantLock(); lock.lock(); lock.unlock();
*/
public class ThreadSynchron
{
private static int count = 20;
public static void main( String[] args ) {
ThreadSynchron app = new ThreadSynchron();
app.test();
}
public void test(){
Thread thread1 = new TestThread1("窗口1");
Thread thread2 = new TestThread1("窗口2");
Thread thread3 = new TestThread1("窗口3");
Thread thread4 = new TestThread1("窗口4");
Thread thread5 = new TestThread1("窗口5");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}
class TestThread1 extends Thread {
public TestThread1(String name){
super.setName(name);
}
@Override
public void run() {
while (count > 0) {
subtractCount3();
}
}
}
/**
* 在subtractCount方法上添加 synchronized -> private synchronized void subtractCount()
*/
private synchronized void subtractCount() {
if (count <= 0)
return;
if (count > 0) {
System.out.println(Thread.currentThread().getName() + " 售出第 " + count + " 张票!");
count--;
} else {
System.out.println(Thread.currentThread().getName() + " 票卖完了");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 在代码中添加 synchronized 块
*/
private void subtractCount2() {
if(count <=0) return;
synchronized (this) {
if(count > 0){
System.out.println( Thread.currentThread().getName() + " 售出第 " + count + " 张票!");
count--;
}else{
System.out.println(Thread.currentThread().getName() + " 票卖完了");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 第三种方法, 采用 Lock lock=new ReentrantLock(); lock.lock(); lock.unlock();
*/
Lock lock=new ReentrantLock();
private void subtractCount3() {
// 先锁住
lock.lock();
if (count <= 0)
return;
if (count > 0) {
System.out.println(Thread.currentThread().getName() + " 售出第 " + count + " 张票!");
count--;
} else {
System.out.println(Thread.currentThread().getName() + " 票卖完了");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//完事后解锁
lock.unlock();
}
}
开发中, 有的开发人员会不留意的将subtractCount方法定义在线程类中, 那么也会出现线程同步问题, 不相信的话, 你们可以测试试试看!
本文介绍Java中实现线程同步的三种方式:synchronized关键字、synchronized代码块及ReentrantLock锁,并通过售票实例演示如何避免多线程环境下数据混乱。
347

被折叠的 条评论
为什么被折叠?



