synchronized关键字
在上篇文章中,使用了synchronized关键字对共享资源进行锁定,现在就对synchronized关键字进行简单的了解并使用。贴出代码
public class ThreadTest2 {
public static void main(String[] args) {
ThreadTest3 threadTest3 = new ThreadTest3();
new Thread(threadTest3, "线程1").start();
new Thread(threadTest3, "线程2").start();
}
}
class ThreadTest3 implements Runnable {
Integer x = 100;
Object lock = new Object();
@Override
public void run() {
while (true) {
synchronized (ThreadTest3.class) {
try {
Thread.sleep(500);
} catch (Exception e) {
}
if (x > 0) {
System.out.println(Thread.currentThread().getName() + "\t" + x--);
} else {
break;
}
}
}
}
}
代码中synchronized(ThreadTest3.class)达到了全局锁的目的,将资源锁定,即当有一个线程对synchronized修饰的代码块进行访问时,其他线程只能在外等候,进入的线程执行完成后,又会与其他线程共同争抢这个资源,所以会出现某个线程多次连续执行代码块,在上面的代码中添加了Thread.sleep(500); ,使进入的程序休眠,从而实现两个线程循环输出。
synchronized不仅可以加在一段代码上,也可以加在方法上,对方法进行限制, synchronized加在方法上只能防止多个线程同时执行同步代码段。另外 static synchronized方法也相当于全局锁,对代码段进行限制。例子有如下:
1、锁对象,像上面的代码一样
synchronized (ThreadTest3.class) {...}
2、锁方法
public synchronized void run() {...}
3、锁引用类型的变量
class ThreadTest3 implements Runnable {
Integer x = 100;
Object lock = new Object();
@Override
public synchronized void run() {
while (true) {
synchronized (x) {
.......}
}
}
synchronized在使用时会自动加锁、解锁,不像lock()需要手动解锁。自动锁可以一定程度上减少繁琐,但是一旦形成死锁就会很麻烦。
那如果想要线程进行有序的循环访问该怎么办呢?这里就要说Condition了,后续会接着写。
接下来是Synchronized的例子:
1、锁引用类型变量
public class Money {
public static void main(String[] args) throws InterruptedException {
MoneyWindown mw = new MoneyWindown();
Thread mw1 = new Thread(mw, "窗口一");
Thread mw2 = new Thread(mw, "窗口二");
Thread mw3 = new Thread(mw, "窗口三");
Thread mw4 = new Thread(mw, "窗口四");
mw1.start();
mw2.start();
mw3.start();
mw4.start();
}
}
class MoneyWindown implements Runnable {
Integer money = 100;
@Override
public void run() {
synchronized (money) {
while (money > 0) {
System.out.println(Thread.currentThread().getName() + "正在售票\t" + "剩余票数:\t" + money--);
}
}
}
}
效果:
2、锁对象
public class Money {
public static void main(String[] args) throws InterruptedException {
MoneyWindown mw = new MoneyWindown();
Thread mw1 = new Thread(mw, "窗口一");
Thread mw2 = new Thread(mw, "窗口二");
Thread mw3 = new Thread(mw, "窗口三");
Thread mw4 = new Thread(mw, "窗口四");
mw1.start();
mw2.start();
mw3.start();
mw4.start();
}
}
class MoneyWindown implements Runnable {
Integer money = 100;
@Override
public void run() {
synchronized (MoneyWindown.class) {
while (money > 0) {
System.out.println(Thread.currentThread().getName() + "正在售票\t" + "剩余票数:\t" + money--);
}
}
}
}
效果:
3、锁方法
public class Money {
public static void main(String[] args) throws InterruptedException {
MoneyWindown mw = new MoneyWindown();
Thread mw1 = new Thread(mw, "窗口一");
Thread mw2 = new Thread(mw, "窗口二");
Thread mw3 = new Thread(mw, "窗口三");
Thread mw4 = new Thread(mw, "窗口四");
mw1.start();
mw2.start();
mw3.start();
mw4.start();
}
}
class MoneyWindown implements Runnable {
Integer money = 100;
@Override
public synchronized void run() {
//synchronized (MoneyWindown.class) {
while (money > 0) {
System.out.println(Thread.currentThread().getName() + "正在售票\t" + "剩余票数:\t" + money--);
}
//}
}
}
效果: