重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
会放弃CPU资源,锁资源不会放弃的。但是当同步代码执行完毕,资源锁自然就释放了。
创新互联长期为近千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为肥乡企业提供专业的成都做网站、网站设计,肥乡网站改版等技术服务。拥有十余年丰富建站经验和众多成功案例,为您定制开发。
比如说:这样一段代码,同时有多个线程在阻塞等待欲执行这个同步方法
synchronized public boolean print(Integer com)
{
long iii = 100000000;
if(com!=flag)
{
Thread.yield();//直接放弃Cpu资源
while (iii--0);
}
else
{
..............
}
.........return false;.
}
假如yield会立即释放对象监视器,那么while(iii--)几乎就不执行了,但是实际情况是while(iii--)会从100000000变成0,也就是说不会立即释放锁资源。(但是这个方法,从某种角度,会加速释放锁资源,仅个人见解)
可以肯定的说,执行完同步代码块 立即释放 而与run方法没有关系
你这个结果应该是随机的
f()执行完释放this锁,被哪个线程拿到是随机的
主函数也是一个线程(主线程) 如果你join的位置在主函数里面那么理论上是会等那个线程运行完毕才继续往下走
大概写了一个例子,给你看看,你的那个例子来搞死锁比较难搞,主要你是只有一个锁,没有所谓的请求不释放的问题,一般死锁都需要有两个锁或以上的。
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);
}
}
}
}
问问题要把自己疑惑的地方明确的说出来,不然谁知道你想问什么。
lock.notify();作用是唤醒等待的线程。
lock.wait();作用是使当前线程进入等待,一直到该lock被notify
你执行以下下面的代码就明白了。
public class PrintNum {
private byte[] lock = new byte[0];
PrintThread a = new PrintThread("a");
PrintThread b = new PrintThread("b");
public void demo() {
a.start();
b.start();
}
public void printState(){
System.out.println("a state:"+a.getState());
System.out.println("b state:"+b.getState());
}
class PrintThread extends Thread {
public PrintThread(String name) {
this.setName(name);
}
@Override
public void run() {
synchronized (lock) {
for (int i = 0; i 100; i++) {
printState();//控制台输出线程状态
lock.notify();//位置1,程序可正常执行结束
if (i % 10 == 0 0 != i) {
try {
//lock.notify();
//位置2,程序执行到a:99,b:99后无法正常结束
lock.wait();
//位置3,程序执行到a:9,b:9后无法继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.getName() + ": " + i);
}
}
}
}
public static void main(String[] args) {
PrintNum printNum = new PrintNum();
printNum.demo();
}
}
线程的阻塞和唤醒在多线程并发过程中是一个关键点,当线程数量达到很大的数量级时,并发可能带来很多隐蔽的问题。如何正确暂停一个线程,暂停后又如何在一个要求的时间点恢复,这些都需要仔细考虑的细节。在Java发展史上曾经使用suspend()、resume()方法对于线程进行阻塞唤醒,但随之出现很多问题,比较典型的还是死锁问题。如下代码,主要的逻辑代码是主线程启动线程mt一段时间后尝试使用suspend()让线程挂起,最后使用resume()恢复线程。但现实并不如愿,执行到suspend()时将一直卡住,你等不来“canyou get here?”的输出。
public class ThreadSuspend {
public static voidmain(String[] args) {
Thread mt = newMyThread();
mt.start();
try {
Thread.currentThread().sleep(100);
} catch(InterruptedException e) {
e.printStackTrace();
}
mt.suspend();
System.out.println("canyou get here?");
mt.resume();
}
static class MyThreadextends Thread {
public void run() {
while (true) {
System.out.println("running....");
}
}
}
}