用synchronized关键字及concurrent.locks解决线程并发问题

1.测试:未作并发处理

package tcc.test.threadSafeTest;


/**
* @author tcc:
* @version 创建时间:2020年
* 类说明:线程安装测试以:没用synchronized关键字时;
*/
public class ThreadUnSecurity {

static int tickets = 10;

class SellTickets implements Runnable{

@Override
public void run() {
// 未加同步时产生脏数据
while(tickets > 0) {

System.out.println(Thread.currentThread().getName()+"--->售出第: "+tickets+" 票");
tickets--;

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

}

if (tickets <= 0) {

System.out.println(Thread.currentThread().getName()+"--->售票结束!");
}
}
}


public static void main(String[] args) {


SellTickets sell = new ThreadUnSecurity().new SellTickets();

Thread thread1 = new Thread(sell, "1号窗口");
Thread thread2 = new Thread(sell, "2号窗口");
Thread thread3 = new Thread(sell, "3号窗口");
Thread thread4 = new Thread(sell, "4号窗口");

thread1.start();
thread2.start();
thread3.start();
thread4.start();

}

}

结果:

1号窗口--->售出第: 10 票
3号窗口--->售出第: 10 票
2号窗口--->售出第: 10 票
4号窗口--->售出第: 10 票
1号窗口--->售出第: 6 票
3号窗口--->售出第: 5 票
2号窗口--->售出第: 5 票
4号窗口--->售出第: 5 票
1号窗口--->售出第: 2 票
4号窗口--->售出第: 1 票
2号窗口--->售出第: 1 票
3号窗口--->售出第: 1 票
1号窗口--->售票结束!
3号窗口--->售票结束!
4号窗口--->售票结束!
2号窗口--->售票结束!

2.测试:用synchronized同步代码块;或者在方法前加synchronized关键字,写个同步方法

package tcc.test.threadSafeTest;
/**
* @author tcc:
* @version 创建时间:2020年
* 类说明:
*/

public class ThreadSynchronizedSecurity {

static int tickets = 10;

class SellTickets implements Runnable{

@Override
public void run() {
// 同步代码块
while(tickets > 0) {

//其实就是将crud的业务逻辑写在synchronized的保护的作用域中
synchronized (this) {

// System.out.println(this.getClass().getName().toString());

if (tickets <= 0) {

return;
}

System.out.println(Thread.currentThread().getName()+"--->售出第: "+tickets+" 票");
tickets--;

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

if (tickets <= 0) {

System.out.println(Thread.currentThread().getName()+"--->售票结束!");
}
}
}
}


public static void main(String[] args) {


SellTickets sell = new ThreadSynchronizedSecurity().new SellTickets();

Thread thread1 = new Thread(sell, "1号窗口");
Thread thread2 = new Thread(sell, "2号窗口");
Thread thread3 = new Thread(sell, "3号窗口");
Thread thread4 = new Thread(sell, "4号窗口");

thread1.start();
thread2.start();
thread3.start();
thread4.start();


}

}

输出:

1号窗口--->售出第: 10 票
1号窗口--->售出第: 9 票
1号窗口--->售出第: 8 票
1号窗口--->售出第: 7 票
1号窗口--->售出第: 6 票
1号窗口--->售出第: 5 票
1号窗口--->售出第: 4 票
1号窗口--->售出第: 3 票
1号窗口--->售出第: 2 票
1号窗口--->售出第: 1 票
1号窗口--->售票结束!

3.concurrent.locks加锁及释放锁

package tcc.test.threadSafeTest;
/**
* @author tcc:
* @version 创建时间:2020年
* 类说明:lock方法
*/
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadLockSecurity {

static int tickets = 10;

class SellTickets implements Runnable{

Lock lock = new ReentrantLock();

@Override
public void run() {
// Lock锁机制
while(tickets > 0) {

try {
lock.lock();//加锁

if (tickets <= 0) {

return;
}

System.out.println(Thread.currentThread().getName()+"--->售出第: "+tickets+" 票");
tickets--;
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}finally {

lock.unlock();//解锁
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

if (tickets <= 0) {

System.out.println(Thread.currentThread().getName()+"--->售票结束!");
}

}
}


public static void main(String[] args) {


SellTickets sell = new ThreadLockSecurity().new SellTickets();

Thread thread1 = new Thread(sell, "1号窗口");
Thread thread2 = new Thread(sell, "2号窗口");
Thread thread3 = new Thread(sell, "3号窗口");
Thread thread4 = new Thread(sell, "4号窗口");

thread1.start();
thread2.start();
thread3.start();
thread4.start();


}

}

1号窗口--->售出第: 10 票
2号窗口--->售出第: 9 票
4号窗口--->售出第: 8 票
3号窗口--->售出第: 7 票
1号窗口--->售出第: 6 票
2号窗口--->售出第: 5 票
4号窗口--->售出第: 4 票
3号窗口--->售出第: 3 票
1号窗口--->售出第: 2 票
2号窗口--->售出第: 1 票
3号窗口--->售票结束!
1号窗口--->售票结束!
2号窗口--->售票结束!

4.实战中的经验

 

上一篇:【JUC学习】——Lock和Synchronized使用


下一篇:POJ2828 Buy Tickets(线段树二分)