1.Lock
- 解决线程安全问题的方式三:Lock锁 JDK5.0新加
- synchronized 与 Lock的区别:
- 相同点:
- 都是解决线程的安全问题
- 不同点:
- 1.Lock是显示锁(手动开启和关闭锁),synchronized是隐式锁,出了
- 作用域自动释放
- 2.Lock只有代码块锁,synchronized有代码块锁和方法锁
- 3.Lock锁,JVM将花费较少的时间来调度线程,性能更好.并且具有更好的扩展性,
- 提供更多的子类
- 使用优先顺序:
- LOck>>>同步代码块>>>同步方法
// An highlighted block
var foo = 'bar';
class window implements Runnable {
private int ticket = 100;
//1.实例化lock
private ReentrantLock lock = new ReentrantLock(true);//公平锁
@Override
public void run() {
while (true) {
//2.在try finally中lock 和 unlock
try {
lock.lock();
if (ticket > 0) {
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println(Thread.currentThread().getName() + ":售票,票号为:" + ticket);
ticket--;
} else {
break;
}
}finally {
lock.unlock();
}
}
}
}
public class LockTest {
public static void main(String[] args) {
window w = new window();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
2.synchronized
- 多线程
- 1.创建类继承于Thread
- 2.重写run方法,将需要多线程执行的程序写入
- 3.创建对象
- 4.调用start方法
-
- 第二种创建多线程:
- 1.创建一个实现了Runnable接口的类;
- 2.实现类去实现Runnable中的抽象方法:run()
- 3.创建实现类的对象
- 4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
- 5.通过Thread类的对象调用start()
// An highlighted block
var foo = 'bar';
class MThread extends Thread {
Object obj = new Object();
@Override
public void run() {
synchronized (MThread.class) {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i + getPriority() + "副线程");
}
if (i % 20 == 0) {
yield();
}
}
}
}
}
public class ThreadMethodTest {
public static void main(String[] args) {
MThread t1 = new MThread();
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();//启动当前线程,调用当前线程的run方法
// t1.run(); //只调用方法,不是多线程
System.out.println("thread test");
synchronized (ThreadMethodTest.class) {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + i + Thread.currentThread().getPriority() + "**********主线程**********");
}
if (i == 20) {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
System.out.println(t1.isAlive());
}
}
3.关于死锁
死锁
- 1.不同的线程分贝占用对方需要的同步资源不放弃,都在等对方放弃自己需要的同步资源,就形成了线程的死锁
- 2.出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续。
*解决办法:
- 1.专门的算法/原则
- 2.尽量减少同步资源的定义
- 3.尽量避免嵌套同步
// An highlighted block
var foo = 'bar';
public class DeadLock1 {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
StringBuffer s2 = new StringBuffer();
// 匿名继承Thread,嵌套同步锁
new Thread(){
@Override
public void run() {
synchronized (s1){
s1.append("a");
s2.append("1");
// 阻塞0.1s,增加另外线程获取对象作为锁的概率,形成死锁状态
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s2){
s1.append("b");
s2.append("2");
System.out.println(s1);
System.out.println(s2);
}
}
}
}.start();
// 匿名实现Runable接口,嵌套同步锁
new Thread(new Runnable() {
@Override
public void run() {
synchronized (s2){
s1.append("c");
s2.append("3");
// 阻塞0.1s,增加另外线程获取对象作为锁的概率,形成死锁状态
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s1){
s1.append("d");
s2.append("4");
System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();
}
}