Выкарыстанне «гэта» супраць іншага аб'екта, як замак у сінхранізаваны блок з чаканнем і апавяшчэння

У мяне ёсць два блокі кода, адзін чакае іншага, каб паведаміць яго.

synchronized(this) {
    wait();
}

і

while(condition) {
    //do stuff
    synchronized(this) {
        notify();
    }
}

дастаткова Жудасна, не чакаць, пакуль паведаміць гэта зрабіў:

synchronized(objectLock) {
    objectLock.wait();
}

і

while(condition) {
    //do stuff
    synchronized(objectLock) {
        objectLock.notify();
    }
}

I'm very curious about the difference of both sets, і why the first one worked while the other didn't. Note that the two blocks reside in two different threads on two different methods (if that helps).

Я спадзяюся, што хто-то можа растлумачыць, чаму гэта так. Я адрэдагаваў мой пытанне, так што было б больш дэталёва.

3
У большасці выпадкаў выкарыстання, гэта пачакайце называюць гэта змяшчаецца ўнутры ўмова цыклу, а не паведаміць . Я амаль упэўнены, што гэта адносіцца і да вашага справе, а таксама. гэта значыць яна павінна быць , а (умова) {чаканне (); } і Notify() у іншым месцы. Калі вы выкарыстоўваеце шаблон манітора, вы таксама атрымліваеце выгаду ад інкапсуляцыі, і не спатрэбіліся б сінхранізаваныя блокі (вы павінны сінхранізаванага метаду замест гэтага.)
дададзена аўтар amn, крыніца
У большасці выпадкаў выкарыстання, гэта пачакайце называюць гэта змяшчаецца ўнутры ўмова цыклу, а не паведаміць . Я амаль упэўнены, што гэта адносіцца і да вашага справе, а таксама. гэта значыць яна павінна быць , а (умова) {чаканне (); } і Notify() у іншым месцы. Калі вы выкарыстоўваеце шаблон манітора, вы таксама атрымліваеце выгаду ад інкапсуляцыі, і не спатрэбіліся б сінхранізаваныя блокі (вы павінны сінхранізаванага метаду замест гэтага.)
дададзена аўтар amn, крыніца
Гэта вельмі цяжка сказаць <�я> толькі з гэтага фрагмента кода. Мы паняцця не маю, што вы маеце на ўвазе пад «не працуе», ні тое, што астатняя частка кода робіць.
дададзена аўтар Jon Skeet, крыніца
Гэта вельмі цяжка сказаць <�я> толькі з гэтага фрагмента кода. Мы паняцця не маю, што вы маеце на ўвазе пад «не працуе», ні тое, што астатняя частка кода робіць.
дададзена аўтар Jon Skeet, крыніца
Да не працуе, я меў на ўвазе, што не чакаць. Я не ўпэўнены, што гэта дастаткова, але гэта даволі шмат, сутнасць за ўсё.
дададзена аўтар Chad, крыніца
Да не працуе, я меў на ўвазе, што не чакаць. Я не ўпэўнены, што гэта дастаткова, але гэта даволі шмат, сутнасць за ўсё.
дададзена аўтар Chad, крыніца

8 адказы

Гэта не спрацавала, таму што вы сінхранізаваныя на гэта , які ў два розных нитея ўказвае на два розныя тэма аб'ектаў.

Сінхранізацыя з чакаць() і Notify() будзе працаваць толькі пры сінхранізацыі на той жа аб'ект для блакавання як objectLock , які вы выкарыстоўвалі пазней на.

EDIT: If the two thread instances belonged to the same MyThread class then to achieve the effect that you thought you're code was having, you would have to acquire a lock on their class object itself:

synchronized(MyThread.class)
2
дададзена
@ Ngọcminh.oss Так, вы маеце рацыю. На самай справе, з дапамогай ReentrantLock дазволіць нам выкарыстоўваць замак у іншых перадавых спосабаў. (TryLock() і г.д.) Але, я думаю, што OP тут проста спрабую даведацца, як працуюць першыя асновы.
дададзена аўтар Ravi Thapliyal, крыніца
Так, таму што выпадкі, што два «гэта» былі павернутыя ў розныя былі (хоць, калі іх клас быў той жа). Просты!
дададзена аўтар Ravi Thapliyal, крыніца
Калі два асобніка ніткі належаць да аднаго і таго ж MyThread клас, то для дасягнення таго, што вы хочаце, вы павінны быць заблакаваныя на сінхранізаваць (MyThread.class) аб'екта.
дададзена аўтар Ravi Thapliyal, крыніца
Вы павінны пазбягаць блакавання на той ці іншы агульнадаступны аб'ект як MyThread.class. Код іншых можа выпадкова ўзаемадзейнічаць з ім, а таксама. Я думаю, выкарыстоўваць спецыяльны і прыватны аб'ект блакавання з'яўляецца лепшай практыкай.
дададзена аўтар ngọcminh.oss, крыніца
Цяпер я б атрымаў яго, так як пражываў у двух розных патоках, нават калі гэтыя метады былі абодва ў тым жа выпадку, гэта будзе ставіцца да тэмы не задзірлівы аб'екта. Прывітання.
дададзена аўтар Chad, крыніца
Але не гэта павінен паказваць на асобнік класа, у якім абодва метаду ставяцца, да якіх таксама адносіцца і да гэтай справы?
дададзена аўтар Chad, крыніца

Гэта не спрацавала, таму што вы сінхранізаваныя на гэта , які ў два розных нитея ўказвае на два розныя тэма аб'ектаў.

Сінхранізацыя з чакаць() і Notify() будзе працаваць толькі пры сінхранізацыі на той жа аб'ект для блакавання як objectLock , які вы выкарыстоўвалі пазней на.

EDIT: If the two thread instances belonged to the same MyThread class then to achieve the effect that you thought you're code was having, you would have to acquire a lock on their class object itself:

synchronized(MyThread.class)
2
дададзена
@ Ngọcminh.oss Так, вы маеце рацыю. На самай справе, з дапамогай ReentrantLock дазволіць нам выкарыстоўваць замак у іншых перадавых спосабаў. (TryLock() і г.д.) Але, я думаю, што OP тут проста спрабую даведацца, як працуюць першыя асновы.
дададзена аўтар Ravi Thapliyal, крыніца
Так, таму што выпадкі, што два «гэта» былі павернутыя ў розныя былі (хоць, калі іх клас быў той жа). Просты!
дададзена аўтар Ravi Thapliyal, крыніца
Калі два асобніка ніткі належаць да аднаго і таго ж MyThread клас, то для дасягнення таго, што вы хочаце, вы павінны быць заблакаваныя на сінхранізаваць (MyThread.class) аб'екта.
дададзена аўтар Ravi Thapliyal, крыніца
Вы павінны пазбягаць блакавання на той ці іншы агульнадаступны аб'ект як MyThread.class. Код іншых можа выпадкова ўзаемадзейнічаць з ім, а таксама. Я думаю, выкарыстоўваць спецыяльны і прыватны аб'ект блакавання з'яўляецца лепшай практыкай.
дададзена аўтар ngọcminh.oss, крыніца
Цяпер я б атрымаў яго, так як пражываў у двух розных патоках, нават калі гэтыя метады былі абодва ў тым жа выпадку, гэта будзе ставіцца да тэмы не задзірлівы аб'екта. Прывітання.
дададзена аўтар Chad, крыніца
Але не гэта павінен паказваць на асобнік класа, у якім абодва метаду ставяцца, да якіх таксама адносіцца і да гэтай справы?
дададзена аўтар Chad, крыніца

Вы можаце выкарыстоўваць любы аб'ект, які вы любіце. Аднак, як правіла, больш зразумела для іншых праграмістаў, каб убачыць відавочны аб'ект блакавання.

Мая дзікая здагадка, чаму гэтай не працуе для вас, вы мелі іншы гэта у вобласці бачнасці. (Гэта значыць, у ананімнай функцыі/зваротнага выкліку). Вы можаце быць цалкам зразумела, якую гэта выкарыстоўваць, дадаючы імя класа, напрыклад, WonderClass.this - зноў прычына гэта не ясна. (Рэдагаванне: на самай справе WhateverClass.this не дапаможа, калі гэта на самой справе іншы асобнік)

Таксама не прачытаць: http://docs.oracle.com/javase/ падручнік/Эфірны/паралелізм/locksync.html - Я наогул лічу прасцей паставіць усе ніткі небяспечнага кода ў невялікія сінхранізаваных метады (якія робяць блакаванне няяўнай на гэтым)

2
дададзена

Вы можаце выкарыстоўваць любы аб'ект, які вы любіце. Аднак, як правіла, больш зразумела для іншых праграмістаў, каб убачыць відавочны аб'ект блакавання.

Мая дзікая здагадка, чаму гэтай не працуе для вас, вы мелі іншы гэта у вобласці бачнасці. (Гэта значыць, у ананімнай функцыі/зваротнага выкліку). Вы можаце быць цалкам зразумела, якую гэта выкарыстоўваць, дадаючы імя класа, напрыклад, WonderClass.this - зноў прычына гэта не ясна. (Рэдагаванне: на самай справе WhateverClass.this не дапаможа, калі гэта на самой справе іншы асобнік)

Таксама не прачытаць: http://docs.oracle.com/javase/ падручнік/Эфірны/паралелізм/locksync.html - Я наогул лічу прасцей паставіць усе ніткі небяспечнага кода ў невялікія сінхранізаваных метады (якія робяць блакаванне няяўнай на гэтым)

2
дададзена

Я б параіў выкарыстоўваць шаблон манітора ( http://en.wikipedia.org/wiki/Monitor_ (сінхранізацыя) ) у любым выпадку, гэта можа выратаваць вас ад памылак у далейшым, асабліва ваш выпадак выкарыстання становіцца ўсё больш складаным:

class Monitor
{
    /** Initialised to `false` by default in Java. */
    boolean condition;

    synchronized void waitForSomething()
    {
        while(!condition)
        {
            wait();
        }
    }

    synchronized void signal()
    {
        condition = true;

        notify();
    }
}

Такім чынам, усё прыгожа інкапсулюецца і абароненыя (я звычайна не выкарыстоўваць прыватныя мадыфікатараў ў прыкладах, але вы можаце ўжываць дадатковыя «прыватнасць» ў вашым кодзе, у прыватнасці, робячы ўмова прыватны .)

Як вы можаце заўважыць, у маім стане цыкла ёсць чакаць() выклік, у адрозненне ад вашага прыкладу, дзе ў вас ёсць Notify() у цыкле замест. У большасці выпадкаў выкарыстанне рабіць тое, што вы зрабілі з паведамляюць гэта памылка, хоць я не магу гаварыць для вашага канкрэтнага выпадку, як вы не далі нам дастаткова падрабязна. Я гатовы трымаць заклад, ваш тыповы адзін, хоць, для якіх мадэль манітора ўжываецца прыгожа.

Сцэнар выкарыстання па наступным: нітка, якая хоча чакаць нешта выклікае waitForSomething , а іншы паток можа выклікаць яго працягнуць шляхам выкліку сігнал метад, які будзе ўсталяваны сцяг ўмовы.

1
дададзена

Я б параіў выкарыстоўваць шаблон манітора ( http://en.wikipedia.org/wiki/Monitor_ (сінхранізацыя) ) у любым выпадку, гэта можа выратаваць вас ад памылак у далейшым, асабліва ваш выпадак выкарыстання становіцца ўсё больш складаным:

class Monitor
{
    /** Initialised to `false` by default in Java. */
    boolean condition;

    synchronized void waitForSomething()
    {
        while(!condition)
        {
            wait();
        }
    }

    synchronized void signal()
    {
        condition = true;

        notify();
    }
}

Такім чынам, усё прыгожа інкапсулюецца і абароненыя (я звычайна не выкарыстоўваць прыватныя мадыфікатараў ў прыкладах, але вы можаце ўжываць дадатковыя «прыватнасць» ў вашым кодзе, у прыватнасці, робячы ўмова прыватны .)

Як вы можаце заўважыць, у маім стане цыкла ёсць чакаць() выклік, у адрозненне ад вашага прыкладу, дзе ў вас ёсць Notify() у цыкле замест. У большасці выпадкаў выкарыстанне рабіць тое, што вы зрабілі з паведамляюць гэта памылка, хоць я не магу гаварыць для вашага канкрэтнага выпадку, як вы не далі нам дастаткова падрабязна. Я гатовы трымаць заклад, ваш тыповы адзін, хоць, для якіх мадэль манітора ўжываецца прыгожа.

Сцэнар выкарыстання па наступным: нітка, якая хоча чакаць нешта выклікае waitForSomething , а іншы паток можа выклікаць яго працягнуць шляхам выкліку сігнал метад, які будзе ўсталяваны сцяг ўмовы.

1
дададзена

Калі вы кажаце, што два блокі знаходзяцца ў двух розных плыняў, што прымушае мяне думаць, што яны не выракаць на тым жа аб'екце, таму што гэта гэта не тое ж самае. Калі вы называеце відавочную блакаванне вы карыстаецеся тое ж самае, каб прывязвацца.

Дарэчы, вы павінны выклікаць пачакайце у цыкле, як гэта:

synchronized(someLock) {
   while (!someCondition) {
       wait();
   }
  //now the thread has the lock and it can do things 
  //knowing for sure that someCondition is true
}

Без гэтага вы будзеце ўразлівыя да ілжывым абуджэння (не ўсё апавяшчэнні прыходзяць з вашага кода прыкладання), а таксама парадак, у якім пачакайце і паведаміць называюцца становіцца праблематычным (калі ў вас ёсць два ніткі і адзін апавяшчае перад іншымі чакае тое, што апавяшчэнне ніколі не будуць бачныя).

1
дададзена

Калі вы кажаце, што два блокі знаходзяцца ў двух розных плыняў, што прымушае мяне думаць, што яны не выракаць на тым жа аб'екце, таму што гэта гэта не тое ж самае. Калі вы называеце відавочную блакаванне вы карыстаецеся тое ж самае, каб прывязвацца.

Дарэчы, вы павінны выклікаць пачакайце у цыкле, як гэта:

synchronized(someLock) {
   while (!someCondition) {
       wait();
   }
  //now the thread has the lock and it can do things 
  //knowing for sure that someCondition is true
}

Без гэтага вы будзеце ўразлівыя да ілжывым абуджэння (не ўсё апавяшчэнні прыходзяць з вашага кода прыкладання), а таксама парадак, у якім пачакайце і паведаміць называюцца становіцца праблематычным (калі ў вас ёсць два ніткі і адзін апавяшчае перад іншымі чакае тое, што апавяшчэнне ніколі не будуць бачныя).

1
дададзена