新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
你的代码我没看,也没运行。
肃宁ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:18982081108(备注:SSL证书合作)期待与您的合作!
但我可以很明确的告诉你,你是没有办法控制线程的执行顺序的,不知道你学没学操作系统,等你学了线程调度你就知道为什么了,多线程的一个特点就是不可重现性。像sleep这些函数只能在一定程度上控制你的线程执行,但根本不是绝对的。因为当线程1在sleep时,系统也不一定会调用另一线程。
还有加锁也不是为了控制线程的执行顺序,它的目的是为了保护共享的互斥资源。
锁的竞争只发生在多个线程之间,代码中两个synchronized(a)在同一个线程里面(而且是一层包着另一层,里面的synchronized(a)变得毫无意义),所以能执行
// 我不想分析你的问题,但是我发一段我写的死锁代码
package com.demo;
public class DeadLock implements Runnable{
//测试死锁的例子;
//声明两个KEY;用于加锁使用;
private static final String KEY1="KEY1";
private static final String KEY2="KEY2";
private boolean lock;
public DeadLock(boolean lock){
this.lock = lock;
//调用boolean true|false 赋值给lock进行判断key1和key2;
}
public void run(){
if(lock){
synchronized(KEY1){//第一次锁KEY1
try{
Thread.sleep(3000);
}catch(Exception e){
}
System.out.println("给我KEY2我要使用!");
synchronized(KEY2){//第二次锁KEY2
System.out.println("我拿到KEY2运行结束!");
}
}
}else{
synchronized(KEY2){//第一次锁KEY2
try{
Thread.sleep(3000);
}catch(Exception e){
}
System.out.println("Give me KEY1,I will use!");
synchronized(KEY1){//第二次锁KEY1
System.out.println("我拿到KEY1运行结束!");
}
}
}
}
public static void main(String args[]){
new Thread(new DeadLock(true)).start();
new Thread(new DeadLock(false)).start();
}
}
在我的记忆中执行wait()方法后,线程的锁都会被释放吧,
所以在你调用wait后,list这个锁应该已经释放了。
大概写了一个例子,给你看看,你的那个例子来搞死锁比较难搞,主要你是只有一个锁,没有所谓的请求不释放的问题,一般死锁都需要有两个锁或以上的。
public class TestT {
public static void main(String[] args) {
for (int i = 0; i 10; i ++) {
NumThread nt = new NumThread(1,2);
NumThread nt2 = new NumThread(2,1);
nt.start();
nt2.start();
}
}
}
class NumThread extends Thread{
private int a;
private int b;
public NumThread(int a,int b) {
this.a = a;
this.b = b;
}
public void run() {
synchronized(Integer.valueOf(a)) {
System.out.println("xxx" + Thread.currentThread().getName());
synchronized(Integer.valueOf(b)) {
System.out.println("yyy" + Thread.currentThread().getName());
}
}
}
}
这个例子首先需要先了解Integer类的机制,再进行Integer类实例化或转换时,它会缓存-128-127之间的所有对象,因此在这里我们,调用的1,2至始至终都只有两个对象。
下面就是死锁的分析:
当我们执行NumThread(1,2)时,锁的取得没问题(Integer.valueOf(a)的锁肯定没问题),接下来用NumThread(2,1),如果此时NumThread(1,2)已经取得了两个锁,这里没问题,执行完后可以继续取得锁,但如果NumThread(1,2)只取得a的锁,而此时NumThread(2,1)取得了b的锁,这时问题就来了。NumThread(1,2)会等待NumThread(2,1)释放b锁,而NumThread(2,1)会等等NumThread(1,2)释放a锁。
我用了一个循环启动线程是因为发生的机率不大。
可以引伸到你那个例子,用两个相同的对象作为锁。
public class TestT {
public static void main(String[] args) {
S s = new S();
S s2 = new S();
for (int i = 0; i 10; i ++) {
TestSleep ts = new TestSleep(s,s2);
TestSleep ts2 = new TestSleep(s2,s);
ts.start();
ts2.start();
}
}
}
class S{public int i=0;}
class TestSleep extends Thread {
/**
* @param args
*/
private S s=null;
private S s2 = null;
public TestSleep(S s,S s2){
this.s=s;
this.s2=s2;
}
public void run(){
System.out.println("Now is begin Thread-A");
synchronized(s){
System.out.println("Now is begin "+Thread.currentThread().getName());
synchronized(s2) {
System.out.println(s.i);
}
}
}
}
(1) tt是实现了runnable接口,而Thread的构造方法需要一个实现了runnable接口的实例
(2) 锁得不是方法,是对象,也就是this.可以用锁代码是synchronized(对象){代码}方式。如果直接对方法用synchronized锁得就是放在所在的对象
(3)是使用了synchronized修饰的代码就不能有锁了,如果没用synchronized修饰,还是可以执行的
(4)去掉synchronized后m2方法就锁不住了,所以在m1()输出前把b给改了