线程同步
线程同步的方法
1.同步代码块
synchronize(){
}
包住需要同步的代码段(保证仅包含对共享变量的操作)
括号中填同步监视器,也就是锁,可以是任何一个类的对象
关键就是多个线程要用同一把锁,否则达不到效果
实现Runnable接口方法
package Test1; /** * @author rook1e * @creat 2022/1/9 */ class Window implements Runnable{ private int ticket = 100; Object obj = new Object(); public void run(){ while(true){ synchronized(obj) { if (ticket > 0) { System.out.println(Thread.currentThread().getName() + ":" + ticket); --ticket; } else { break; } } } } } public class WindowTicket { public static void main(String[] args) { Window window = new Window(); Thread t1 = new Thread(window); Thread t2 = new Thread(window); Thread t3 = new Thread(window); t1.setName("Window 1"); t2.setName("Window 2"); t3.setName("Window 3"); t1.start(); t3.start(); t2.start(); } }
继承Thread类方法
package Test1; /** * @author rook1e * @creat 2022/1/9 */ class Window extends Thread{ private static int ticket = 100; private static Object obj = new Object(); public void run(){ while(true){ synchronized(obj) { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + ticket); --ticket; } else { break; } } } } } public class WindowTicket { public static void main(String[] args) { Window window1 = new Window(); Window window2 = new Window(); Window window3 = new Window(); window1.setName("window1"); window2.setName("window2"); window3.setName("window3"); window1.start(); window2.start(); window3.start(); } }
特别的,如果每次new一个对象有些麻烦,我们可以直接使用当前对象this,更简便一点
但是要注意如果使用继承方式实现多线程时,需要new多个类,要明确当前的this是否是唯一的,换句话说就是,多个线程需要共用同一个this!
2.同步方法
对仅对共享变量操作的方法,直接声明为同步方法
package Test1; /** * @author rook1e * @creat 2022/1/10 */ class Window1 implements Runnable{ private int ticket = 100; public void run(){ while(true){ show(); } } private synchronized void show(){ if(ticket > 0){ System.out.println(Thread.currentThread().getName() + ":" + ticket); -- ticket; } } } public class WindowSynchronized { public static void main(String[] args) { Window1 window1 = new Window1(); Thread t1 = new Thread(window1); Thread t2 = new Thread(window1); Thread t3 = new Thread(window1); t1.setName("Window1"); t2.setName("Window2"); t3.setName("Window3"); t1.start(); t2.start(); t3.start(); } }
不能将run方法声明为同步方法,否则是错误的,要保证同步方法中仅包含对共享变量的操作。
3.lock锁
使用java中定义的锁,包含用lock方法和unlock方法包含需要同步的代码段,实现解决线程安全问题
下面是实现Runnable接口方法实现多线程
package Test1; import java.util.concurrent.locks.ReentrantLock; /** * @author rook1e * @creat 2022/1/8 */ class MthreadTickets implements Runnable{ public static int tickets = 100; private ReentrantLock lock = new ReentrantLock(); @Override public void run() { while(true){ lock.lock();//上锁 if(tickets > 0){ System.out.println(Thread.currentThread().getName() + ":" + "id " + tickets); tickets -- ; }else{ break; } lock.unlock();//解锁 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class ThreadTickets { public static void main(String[] args) { MthreadTickets mthreadTickets = new MthreadTickets(); Thread t1 = new Thread(mthreadTickets); Thread t2 = new Thread(mthreadTickets); Thread t3 = new Thread(mthreadTickets); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); } }
继承Threa类方式实现多线程,同一样的,多个线程需要共用同一把锁,因此声明锁时需要加上static关键字来实现唯一性
package Test1; import java.util.concurrent.locks.ReentrantLock; /** * @author rook1e * @creat 2022/1/9 */ class Window extends Thread{ private static int ticket = 100; private static ReentrantLock lock = new ReentrantLock();//注意加static关键字的原因 public void run(){ while(true){ lock.lock(); if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + ticket); --ticket; } else { break; } lock.unlock(); } } } public class WindowTicket { public static void main(String[] args) { Window window1 = new Window(); Window window2 = new Window(); Window window3 = new Window(); window1.setName("window1"); window2.setName("window2"); window3.setName("window3"); window1.start(); window2.start(); window3.start(); } }
package Test1;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author rook1e
* @creat 2022/1/9
*/
class Window extends Thread{
private static int ticket = 100;
private static ReentrantLock lock = new ReentrantLock();
public void run(){
while(true){
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket);
--ticket;
} else {
break;
}
lock.unlock();
}
}
}
public class WindowTicket {
public static void main(String[] args) {
Window window1 = new Window();
Window window2 = new Window();
Window window3 = new Window();
window1.setName("window1");
window2.setName("window2");
window3.setName("window3");
window1.start();
window2.start();
window3.start();
}
}