一、没用锁之前出现的问题
package day34_thread_线程.线程锁;
/*
* t1,t2,t3
* 假设只剩一张票
* t1过来了,他一看有票,他就进来了,但是他突然肚子不舒服,然后他就去上卫生间了
* t2也过来了,他一看也有票,他也进来了,但是他的肚子也不舒服,他也去上卫生间了
*
* t1上完了卫生间回来了,开始售票
* tickets = 0;
* t2也上完卫生间回来了,他也进行售票
* tickets = -1;
*
*
*/
public class SleepThread implements Runnable {
int nums = 20;
@Override
public void run() {
// if(num > 0) {
// for(int i=0;i<100;i++) {
// System.out.println(Thread.currentThread().getName() + ":" + i);
// }
while(true) {
if(nums > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + nums--);
}else {
System.exit(0);
}
}
}
}
package day34_thread_线程.线程锁;
/*
* 模拟火车站售票
*
* 分析:
* 首相需要有火车票的总数量,每售出一张则数量减一
* 当火车票的数量小于1的时候,停止售票
* 使用多线程模拟多个窗口进行售票
* 当火车票全部售完,火车站也一样敞开大门欢迎我们
*
* static void sleep(long millis) : 让当前线程睡一会
*/
public class SleepDemo {
public static void main(String[] args) {
SleepThread st = new SleepThread();
Thread t = new Thread(st);
t.setName("窗口1");
t.start();
Thread t1 = new Thread(st);
t1.setName("窗口2");
t1.start();
Thread t2 = new Thread(st);
t2.setName("窗口3");
t2.start();
}
}
输出:会出现票的争夺,


二、使用线程锁解决
synchronized是java中的一个关键字,修饰符。
synchronized:同步(锁),可以修饰代码块和方法,被修饰的代码块和方法一旦被某个线程访问,则直接锁住,其他的线程将无法访问
同步代码块:
synchronized(锁对象){
}
同步方法:
public synchronized void method() {
}
synchronized代码块又分为这么几种:synchronized(this),synchronized(className.class)和synchronized(Object obj)
* synchronized(this):修饰非静态方法,锁都在当前对象,只限制当前对象对该代码块的同步。
* synchronized(className.class 字节码对象):修饰静态方法,锁在类而不在类对象,只要是className类对象访问该代码块都被要求同步。
* synchronized(Object obj) :这时锁就是对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁
1. 代码块
package day34_thread_线程.线程锁;
public class SynchronizedThtread implements Runnable {
//火车票数 20
int num = 20;
Object obj = new Object();
@Override
public void run() {
while(true) {
synchronized(obj) {
try{Thread.sleep(100);
}catch (InterruptedException e) {
e.printStackTrace();
}
if(num > 0) {
System.out.println(Thread.currentThread().getName() + ":" + num--);
}
}
}
}
}
public class SynDemo {
public static void main(String[] args) {
SynchronizedThtread st = new SynchronizedThtread();
Thread t = new Thread(st);
t.setName("窗口1");
t.start();
Thread t1 = new Thread(st);
t1.setName("窗口2");
t1.start();
Thread t2 = new Thread(st);
t2.setName("窗口3");
t2.start();
}
}
输出:
线程切换,但是票数按顺序减少,符合要求

2.静态方法、非静态方法
package day34_thread_线程.线程锁;
public class SynFunThread implements Runnable {
/*static int num = 100;*/
int num = 20;
@Override
public void run() {
method();
}
private synchronized void method() {
while(true) {
if(num > 0) {
try{Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + num--);
}
}
}
/* private static synchronized void method() {
while(true) {
if(num > 0) {
try{Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + num--);
}
}
}*/
}
public class SynFunDemo {
public static void main(String[] args) {
SynFunThread sft = new SynFunThread();
Thread t = new Thread(sft);
Thread t1 = new Thread(sft);
Thread t2 = new Thread(sft);
t.start();
t1.start();
t2.start();
}
}
输出:

来源:https://www.cnblogs.com/longesang/p/11340919.html