1.在多线程编程,一些敏感数据不允许被多个绒程同时访问,此时就使用同步访问术,保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性。
2.也可以这里理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作.
线程同步机制的使用
互斥锁
1.Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。
2.每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在能有一个线程访问该对象。
3.关键字synchronized 来与对象的互斥锁联系。当某个对象用synchronized
表明该对象在任一时刻只能由一个线程访问
4.同步的局限性:导致程序的执行效率要降低
5.同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)
6.同步方法(静态的)的锁为当前类本身。’
使用互斥锁来解决售票问题
给代码块加锁
package program;
public class SellTicket2 {
public static void main(String[] args) {
Thread thread = new Tickets();
thread.start();
Thread thread2 = new Tickets();
thread2.start();
Thread thread3 = new Tickets();
thread3.start();
}
}
class Tickets extends Thread {
private static int tickets = 100;
private boolean loop = true;
//方式一 代码块加锁
public void sell() {
synchronized (this) {
if (tickets <= 0){
System.out.println("售票结束");
loop = false;
return;
}
try {
Thread.sleep(50);//休眠50毫秒
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + "售出了一张票,剩余票数:" + (--tickets));
}
}
@Override
public void run() {
while (loop) {
sell();
}
}
}
运行结果
给方法加锁
package program;
/**
* @Author 雾潋
* @Version 1.0
* 使用多线程,模拟三个窗口同时售票 100 张
*/
@SuppressWarnings("all")
public class SellTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread thread = new Thread(ticket);
thread.start();//线程一
Ticket ticket1 = new Ticket();
Thread thread1 = new Thread(ticket1);
thread1.start();//线程二
ticket1.setLoop(false);
Ticket ticket2 = new Ticket();
Thread thread2 = new Thread(ticket2);
thread2.start();//线程三
/*//方式二
Ticket2 ticket21 = new Ticket2();
ticket21.start();
Ticket2 ticket22 = new Ticket2();
ticket22.start();
Ticket2 ticket23 = new Ticket2();
ticket23.start();*/
}
}
//方法一
class Ticket implements Runnable{
public static int tickets = 100;
private boolean loop = true; //用于主线程控制子线程退出
public synchronized void f() { //同步方法,在同一时刻,只有一个线程来执行f()方法
if (tickets <= 0) {
System.out.println("售票结束");
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + ",剩余票数:" + (--tickets));
}
@Override
public void run() {
while (loop){
f();
}
}
public boolean isLoop() {
return loop;
}
public void setLoop(boolean loop) {
this.loop = loop;
}
}
给类加锁
package program;
public class SellTicket2 {
public static void main(String[] args) {
Thread thread = new Tickets();
thread.start();
Thread thread2 = new Tickets();
thread2.start();
Thread thread3 = new Tickets();
thread3.start();
}
}
class Tickets extends Thread {
private static int tickets = 100;
private boolean loop = true;
//方式一 代码块加锁
public void sell() {
synchronized (SellTicket2.class) {
if (tickets <= 0){
System.out.println("售票结束");
loop = false;
return;
}
try {
Thread.sleep(50);//休眠50毫秒
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + "售出了一张票,剩余票数:" + (--tickets));
}
}
@Override
public void run() {
while (loop) {
sell();
}
}
}