এই জাভা প্রোগ্রামটি দৃশ্যত এটি হওয়া উচিত নয় (এবং না) সত্ত্বেও কেন এটি সমাপ্ত হয়?


205

আমার ল্যাবটিতে একটি সংবেদনশীল অপারেশন আজ সম্পূর্ণ ভুল হয়েছে। একটি ইলেক্ট্রন মাইক্রোস্কোপের একটি অ্যাকিউউটর তার সীমানা পেরিয়ে গিয়েছিল এবং ঘটনাগুলির একটি শৃঙ্খলের পরে আমি 12 মিলিয়ন ডলার সরঞ্জাম হারিয়েছি। আমি ত্রুটিযুক্ত মডিউলটিতে 40K এর বেশি লাইন সংকুচিত করেছি:

import java.util.*;

class A {
    static Point currentPos = new Point(1,2);
    static class Point {
        int x;
        int y;
        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    public static void main(String[] args) {
        new Thread() {
            void f(Point p) {
                synchronized(this) {}
                if (p.x+1 != p.y) {
                    System.out.println(p.x+" "+p.y);
                    System.exit(1);
                }
            }
            @Override
            public void run() {
                while (currentPos == null);
                while (true)
                    f(currentPos);
            }
        }.start();
        while (true)
            currentPos = new Point(currentPos.x+1, currentPos.y+1);
    }
}

আমি যে আউটপুটটি পাচ্ছি তার কয়েকটি নমুনা:

$ java A
145281 145282
$ java A
141373 141374
$ java A
49251 49252
$ java A
47007 47008
$ java A
47427 47428
$ java A
154800 154801
$ java A
34822 34823
$ java A
127271 127272
$ java A
63650 63651

যেহেতু এখানে কোনও ভাসমান পয়েন্ট গণিত নেই, এবং আমরা সবাই জানি স্বাক্ষরিত পূর্ণসংখ্যাগুলি জাভাতে ওভারফ্লোতে ভাল আচরণ করে, তাই আমি মনে করি এই কোডটিতে কোনও ভুল নেই। যাইহোক, আউটপুটটি নির্দেশ করে যে প্রোগ্রামটি প্রস্থান অবস্থায় পৌঁছায়নি, এটি প্রস্থান শর্তে পৌঁছেছে (এটি উভয়ই পৌঁছেছিল এবং পৌঁছেছে না?)। কেন?


আমি লক্ষ্য করেছি যে এটি কিছু পরিবেশে ঘটে না। আমি J৪- বিট লিনাক্সের ওপেনজেডকে on এ আছি ।


41
12 মিলিয়ন সরঞ্জাম? আমি সত্যিই আগ্রহী যে কীভাবে এটি ঘটতে পারে ... আপনি খালি সিঙ্ক্রোনাইজেশন ব্লকটি কেন ব্যবহার করছেন: সিঙ্ক্রোনাইজড (এটি)}}?
মার্টিন ভি।

84
এটি এমনকি দূরবর্তীভাবে থ্রেড-নিরাপদ নয়।
ম্যাট বল

8
নোট আকর্ষণীয়: যোগ finalকোয়ালিফায়ার ক্ষেত্র (যা উত্পাদিত বাইটকোড উপর কোনো প্রভাব নেই) xএবং y"সমাধান" বাগ। যদিও এটি বাইটোকোডকে প্রভাবিত করে না, ক্ষেত্রগুলি এটির সাথে পতাকাযুক্ত রয়েছে, যা আমাকে ভাবতে পরিচালিত করে যে এটি একটি জেভিএম অপ্টিমাইজেশনের পার্শ্ব-প্রতিক্রিয়া।
নিভ স্টেইনগার্টেন

9
@ ইউজিন: এটি শেষ হওয়া উচিত নয় । প্রশ্নটি "কেন এটি শেষ হয়?"। এ নির্মিত Point pহয় যা সন্তুষ্ট হয় p.x+1 == p.y, তারপরে ভোটার থ্রেডে একটি রেফারেন্স দেওয়া হয়। অবশেষে ভোটগ্রহণের থ্রেডটি প্রস্থান করার সিদ্ধান্ত নেয় কারণ এটি মনে করে যে এটির যে কোনও একটির জন্য শর্তটি সন্তুষ্ট নয় Point, তবে কনসোল আউটপুট দেখায় যে এটি সন্তুষ্ট হওয়া উচিত ছিল। এখানে অভাবের volatileসহজ অর্থ হ'ল ভোটদানের সূত্রটি আটকে যেতে পারে, তবে এটি স্পষ্টতই এখানে সমস্যা নয়।
এরমা কে পিজারো

21
@ জননিচোলাস: আসল কোডটিতে (যা স্পষ্টতই এটি নয়) ১০০% পরীক্ষার কভারেজ এবং কয়েক হাজার পরীক্ষা ছিল, যার মধ্যে অনেকগুলি বিভিন্ন আদেশ ও ক্রমবিন্যাসের মধ্যে পরীক্ষা করেছিল ... পরীক্ষা নিরীক্ষামূলকভাবে নির্ধারিত প্রতিটি প্রান্তের ক্ষেত্রে ম্যাজিকভাবে খুঁজে পাওয়া যায় না Test জে আই টি JIT / ক্যাশে / নির্ধারণকারী। আসল সমস্যাটি হ'ল এই বিকাশকারী যিনি এই কোডটি লিখেছেন তা জানতেন না যে অবজেক্টটি ব্যবহারের আগে নির্মাণ হয় না। লক্ষ্য করুন কীভাবে খালি অপসারণ synchronizedত্রুটি ঘটায় না? কারণ আমি এলোমেলোভাবে কোড লিখতে হয়েছিল যতক্ষণ না আমি এমন কোনও আবিষ্কার খুঁজে পেয়েছি যা এই আচরণকে নির্জনে পুনরুত্পাদন করতে পারে।
কুকুর

উত্তর:


140

স্পষ্টতই কারেন্টপোসে লেখাটি হ'ল না - এটি পড়ার আগে, তবে কীভাবে এটি সমস্যা হতে পারে তা আমি দেখছি না।

currentPos = new Point(currentPos.x+1, currentPos.y+1);ডিফল্ট মান লিখতে xএবং y(0) এবং তারপরে কনস্ট্রাক্টরে তাদের প্রাথমিক মানগুলি সহ কয়েকটি কাজ করে। যেহেতু আপনার অবজেক্টটি নিরাপদে প্রকাশিত হয়নি সেগুলি 4 রাইট অপারেশনগুলি নির্দ্বিধায় সংকলক / জেভিএম দ্বারা পুনঃক্রম করতে পারে।

সুতরাং পঠন থ্রেডের দৃষ্টিকোণ থেকে, xএটির নতুন মান সহ তবে yউদাহরণস্বরূপ 0 এর ডিফল্ট মান সহ এটি পড়া আইনী সম্পাদন । আপনি printlnবিবৃতিতে পৌঁছানোর সময় (যা উপায় দ্বারা সিঙ্ক্রোনাইজ করা হয় এবং এটি পড়ার ক্রিয়াকলাপগুলিকে প্রভাবিত করে), ভেরিয়েবলগুলির প্রাথমিক মান থাকে এবং প্রোগ্রামটি প্রত্যাশিত মানগুলি মুদ্রণ করে।

currentPosহিসাবে চিহ্নিত করা volatileনিরাপদ প্রকাশনা নিশ্চিত করবে যেহেতু আপনার অবজেক্টটি কার্যকরভাবে অপরিবর্তনীয় - যদি আপনার আসল ব্যবহারের ক্ষেত্রে অবজেক্টটি নির্মাণের পরে পরিবর্তন করা হয় volatileতবে গ্যারান্টি যথেষ্ট হবে না এবং আপনি আবার কোনও বেমানান বস্তু দেখতে পাবেন could

বিকল্পভাবে, আপনি এমন পরিবর্তনহীন করতে পারবেন Pointযা ব্যবহার না করেও নিরাপদ প্রকাশনা নিশ্চিত করবে volatile। অপরিবর্তনীয়তা অর্জনের জন্য, আপনাকে কেবল চিহ্নিত করতে হবে xএবং yচূড়ান্ত করতে হবে।

পার্শ্ব নোট হিসাবে এবং ইতিমধ্যে উল্লিখিত synchronized(this) {}হিসাবে, জেভিএম দ্বারা কোনও অপ-বিকল্প হিসাবে বিবেচনা করা যেতে পারে (আমি বুঝতে পারি যে আপনি আচরণটি পুনরুত্পাদন করতে এটি অন্তর্ভুক্ত করেছেন)।


4
আমি নিশ্চিত নই, তবে মেমরির বাধা এড়িয়ে x এবং y ফাইনালের সাথে একই প্রভাব ফেলবে না?
মাইকেল বাকলিং

3
একটি সহজ ডিজাইন হ'ল একটি পরিবর্তনযোগ্য পয়েন্ট অবজেক্ট যা নির্মাণের উপর আক্রমণকারীদের পরীক্ষা করে। সুতরাং আপনি কখনই বিপজ্জনক কনফিগারেশন প্রকাশের ঝুঁকি নেন না।
রন

@ বন্ধু ক্যাসিনো হ্যাঁ - আমি এটি যুক্ত করেছি। সত্য কথা বলতে গেলে আমি পুরো আলোচনাটি 3 মাস আগে মনে রাখি না (চূড়ান্ত ব্যবহারের মন্তব্যে প্রস্তাব দেওয়া হয়েছিল যাতে নিশ্চিত করে কেন আমি এটিকে বিকল্প হিসাবে অন্তর্ভুক্ত করি নি)।
Assylias

2
অপরিচ্ছন্নতা নিজেই নিরাপদ প্রকাশনার গ্যারান্টি দেয় না (যদি এক্স ওয়াই ব্যক্তিগত হয় তবে কেবল গেটারদের সাথেই উন্মুক্ত হয়, একই প্রকাশনার সমস্যাটি এখনও উপস্থিত থাকবে)। চূড়ান্ত বা অস্থির এটি গ্যারান্টি দেয়। আমি চূড়ান্ত চেয়ে চূড়ান্ত পছন্দ করব।
স্টিভ কুও

@ স্টেভকুও অপ্রয়োজনীয়তা চূড়ান্ত প্রয়োজন - চূড়ান্ত ব্যতীত, আপনি যে সেরাটি পেতে পারেন তা হ'ল কার্যকর অপরিবর্তনশীলতা যা একই শব্দার্থবিজ্ঞান না করে।
Assylias

29

যেহেতু currentPosথ্রেডের বাইরে পরিবর্তন করা হচ্ছে তাই এটি হিসাবে চিহ্নিত করা উচিত volatile:

static volatile Point currentPos = new Point(1,2);

অস্থিরতা ছাড়াই মূল থ্রেডে তৈরি করা কার্টপোসের আপডেটগুলিতে পড়ার গ্যারান্টি নেই। সুতরাং কারেন্টপসের জন্য নতুন মান লেখা যেতে থাকে তবে থ্রেড পারফরম্যান্সের কারণে পূর্ববর্তী ক্যাশেড সংস্করণগুলি ব্যবহার করে চলেছে। যেহেতু শুধুমাত্র একটি থ্রেড কারেন্টপোসকে সংশোধন করে আপনি লক ছাড়াই চলে যেতে পারেন যা কর্মক্ষমতা উন্নত করবে।

ফলাফলগুলি তুলনা এবং পরবর্তী সময়ে প্রদর্শনের জন্য যদি থ্রেডের মধ্যে কেবলমাত্র একবারে মানগুলি পড়েন তবে ফলাফলগুলি আরও আলাদা দেখায়। যখন আমি নিচের কাজগুলো xহিসাবে সবসময় প্রদর্শন 1এবং yমধ্যে তারতম্য ঘটতে পারে 0এবং কিছু বড় পূর্ণসংখ্যা। আমি মনে করি এই মুহুর্তে এর ব্যবহারটি volatileকীওয়ার্ড ব্যতীত কিছুটা সংজ্ঞায়িত এবং এটি সম্ভব যে কোডটির জেআইটি সংকলন এটির মতো আচরণ করে অবদান রাখছে। এছাড়াও যদি আমি খালি synchronized(this) {}ব্লকটি মন্তব্য করি তবে কোডটিও কাজ করে এবং আমার সন্দেহ হয় যে এটি লকিংয়ের ফলে যথেষ্ট বিলম্ব হয় currentPosএবং এর ক্ষেত্রগুলি ক্যাশে থেকে ব্যবহার না করে পুনরায় পড়া হয়।

int x = p.x + 1;
int y = p.y;

if (x != y) {
    System.out.println(x+" "+y);
    System.exit(1);
}

2
হ্যাঁ, এবং আমি কেবল সমস্ত কিছুতে একটি লক রাখতে পারি। তোমার লক্ষ্যটা কি?
কুকুর

আমি ব্যবহারের জন্য কিছু অতিরিক্ত ব্যাখ্যা যুক্ত volatile
এড প্লিজ

19

আপনার কাছে সাধারণ স্মৃতি, 'কারেন্টপোস' রেফারেন্স এবং পয়েন্ট অবজেক্ট এবং এর পিছনে এর ক্ষেত্রগুলি সিঙ্ক্রোনাইজেশন ছাড়াই ২ টি থ্রেডের মধ্যে ভাগ করা হয়েছে। সুতরাং, মূল থ্রেডে এই মেমরির সাথে এবং তৈরি থ্রেডে থাকা পাঠকদের (একে টি বলে ডাকুন) মধ্যে কোনও সংজ্ঞায়িত আদেশ নেই।

প্রধান থ্রেড নিম্নলিখিত লেখাগুলি করছে (পয়েন্টের প্রাথমিক সেটআপ উপেক্ষা করে px এবং পাই এর ডিফল্ট মান থাকবে):

  • to px
  • to py
  • কারেন্টপোসে

সিঙ্ক্রোনাইজেশন / বাধাগুলির ক্ষেত্রে এই লেখাগুলির বিষয়ে বিশেষ কিছু নেই বলে টি-থ্রেডগুলি যে কোনও ক্রমে ঘটে তা দেখতে রানটাইম নির্দ্বিধায় (অবশ্যই মূল থ্রেড সর্বদা প্রোগ্রামের ক্রম অনুসারে লিখতে এবং পড়তে দেখে), এবং ঘটে টি তে পড়ার মাঝে যে কোনও মুহুর্তে

সুতরাং টি করছে:

  1. p তে কারেন্টপোস পড়ে
  2. px এবং পাই পড়ুন (উভয় ক্রমে)
  3. তুলনা করুন, এবং শাখা নিতে
  4. px এবং পাই (উভয় অর্ডার) পড়ুন এবং System.out.println কল করুন

মূলত লেখকের মধ্যে কোনও অর্ডারের সম্পর্ক নেই এবং টি তে পড়ে আছে, প্রদত্ত স্পষ্টভাবে বেশ কয়েকটি উপায় রয়েছে যা এটি আপনার ফলাফল তৈরি করতে পারে, কারণ টি কারেন্টপোস.কে বা কারেন্টপোস.এক্স লেখার আগে কারেন্টপোসে মেইন রচনা দেখতে পারে :

  1. এটি প্রথমে কারেন্টপোস.এক্স পাঠ করে, এক্স রাইট হওয়ার আগে - 0 পায়, তারপরে কারেন্টপোস পড়বে y লেখার আগেই - পেয়ে যায় 0। লেখাগুলি টি.র কাছে দৃশ্যমান হয়ে যায়।
  2. এটি প্রথমে কারেন্টপোস.এক্স পড়ে, এক্স লেখার পরে, তারপরে কারেন্টপোস পড়বে - y লেখার আগেই - পেয়ে যায় ০। পাওয়া যায় সত্যের সাথে তুলনা করুন। লেখাগুলি টিতে দৃশ্যমান হয়ে যায় ... ইত্যাদি etc.
  3. এটি প্রথমে কারেন্টপোস.এ পড়বে, y রাইটিং হওয়ার আগে (0), তারপরে কার্টপোস.এক্স পড়ার পরে এক্স লেখার পরে সত্যটি প্রকাশিত হয়। প্রভৃতি

এবং এভাবেই ... এখানে প্রচুর ডেটা রেস রয়েছে।

আমি সন্দেহ করি যে এখানে ত্রুটিযুক্ত অনুমানটি ভাবছে যে এই রেখাটি থেকে প্রাপ্ত লেখাগুলি থ্রেডের প্রোগ্রাম ক্রমে এটি চালানোর জন্য সমস্ত থ্রেড জুড়ে দৃশ্যমান হয়ে উঠেছে:

currentPos = new Point(currentPos.x+1, currentPos.y+1);

জাভা এ জাতীয় কোনও গ্যারান্টি দেয় না (এটি পারফরম্যান্সের জন্য ভয়ঙ্কর হবে)। আপনার প্রোগ্রামে অন্য থ্রেডে পড়ার তুলনায় লেখকের গ্যারান্টিযুক্ত ক্রম দরকার হলে আরও কিছু যুক্ত করতে হবে। অন্যরা এক্স, ওয়াই ফিল্ড চূড়ান্ত করার বা বিকল্পভাবে কারেন্টপোসকে অস্থির করে তোলার পরামর্শ দিয়েছেন।

  • আপনি যদি x, y ক্ষেত্রগুলি চূড়ান্ত করেন তবে জাভা গ্যারান্টি দেয় যে তাদের মানগুলির লেখাগুলি সমস্ত থ্রেডে কনস্ট্রাক্টর ফেরার আগে দেখা যাবে। সুতরাং, কার্টপোসগুলিতে নির্ধারকের কাজ হিসাবে অ্যাসাইনমেন্টটি হ'ল, টি থ্রেডটি সঠিক ক্রমে লেখাগুলি দেখার গ্যারান্টিযুক্ত।
  • আপনি যদি কারেন্টপোসকে অস্থির করে তুলেন তবে জাভা গ্যারান্টি দেয় যে এটি একটি সিঙ্ক্রোনাইজেশন পয়েন্ট যা সামগ্রিক অর্ডারযুক্ত অন্যান্য সিঙ্ক্রোনাইজেশন পয়েন্ট হবে। কারেন্টপোসে লেখার আগে প্রধান হিসাবে x এবং y অবশ্যই লিখতে হবে, অন্য কোনও থ্রেডে কারেন্টপোস পড়ার আগে অবশ্যই x, y এর লেখাগুলিও দেখতে হবে।

চূড়ান্ত ব্যবহারের সুবিধা রয়েছে যে এটি ক্ষেত্রগুলিকে অপরিবর্তনীয় করে তোলে, এবং এইভাবে মানগুলি ক্যাশে করার অনুমতি দেয়। অস্থির ব্যবহার ব্যবহার করে কারেন্টপোসের প্রতিটি লেখায় এবং পড়ার ক্ষেত্রে সুসংগতকরণ হয় যা কার্য সম্পাদনকে ক্ষতিগ্রস্থ করতে পারে।

গোরো বিবরণের জন্য জাভা ল্যাঙ্গুয়েজ স্পেসের অধ্যায় 17 দেখুন: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html

(প্রাথমিক উত্তরটি একটি দুর্বল মেমরির মডেল হিসাবে ধরেছিল, কারণ আমি নিশ্চিত নই যে জেএলএস গ্যারান্টেড অস্থির যথেষ্ট ছিল Answer অ্যাসিলিয়াসের মন্তব্য প্রতিবিম্বিত করার জন্য সম্পাদনা করা উত্তর, জাভা মডেলটি আরও শক্তিশালী - ঘটনার আগে সংঘটিত - এবং কারেন্টপোসের উপরও অস্থিরতা যথেষ্ট) )।


2
এটি আমার মতে সেরা ব্যাখ্যা। অনেক ধন্যবাদ!
স্কাইড

1
@ স্কাইড তবে অস্থিরতার শব্দার্থবিদ্যায় ভুল। একটি অস্থির গ্যারান্টি দেয় যে একটি অস্থির ভেরিয়েবলের পড়াগুলি একটি উদ্বায়ী ভেরিয়েবলের সর্বশেষ উপলব্ধ লিখনের পাশাপাশি পূর্ববর্তী কোনও লিখন দেখতে পাবে । এই ক্ষেত্রে, যদি currentPosঅস্থির হয়ে থাকে তবে অ্যাসিজনমেন্টটি currentPosবস্তুটির পাশাপাশি তার সদস্যদের নিরাপদ প্রকাশের বিষয়টি নিশ্চিত করে , এমনকি তারা নিজেরাই অস্থির না হলেও।
Assylias

ঠিক আছে, আমি বলছিলাম যে আমি নিজের পক্ষে জেএলএস কীভাবে গ্যারান্টি দিয়েছিলাম যে অস্থায়ী অন্যান্য, সাধারণ পড়তে এবং লেখার সাথে বাধা তৈরি করে see প্রযুক্তিগতভাবে, আমি এতে ভুল হতে পারি না;)। যখন মেমরির মডেলগুলির কথা আসে, তখন অর্ডার দেওয়ার গ্যারান্টিযুক্ত না হওয়া এবং আশেপাশের অন্য উপায়ের চেয়ে ভুল (আপনি এখনও নিরাপদ) এবং ভুল এবং অনিরাপদ হতে হবে তা বুদ্ধিমানের। অস্থির যে গ্যারান্টি সরবরাহ করে তা দুর্দান্ত। আপনি কীভাবে জেএলএস এর Ch 17 এটি সরবরাহ করতে পারেন তা ব্যাখ্যা করতে পারেন?
পৌল

2
সংক্ষেপে, ইন Point currentPos = new Point(x, y), আপনার কাছে 3 টি লিখেছেন: (ডাব্লু 1) this.x = x, (ডাব্লু 2) this.y = yএবং ( ডাব্লু 3 ) currentPos = the new point। প্রোগ্রাম অর্ডার যে গিগাবাইট (ডাব্লু 1, ডাব্লু 3) এবং এইচবি (ডাব্লু 2, ডাব্লু 3) গ্যারান্টি দেয়। পরে প্রোগ্রামটিতে আপনি পড়েন (r1) currentPos। যদি currentPosঅস্থির না হয় তবে আর 1 এবং ডাব্লু 1, ডাব্লু 2, ডব্লু 3 এর মধ্যে কোনও এইচবি নেই, সুতরাং আর 1 তাদের কোনও (বা কোনওটি) পর্যবেক্ষণ করতে পারে। অস্থিরতার সাথে আপনি এইচবি (ডাব্লু 3, আর 1) প্রবর্তন করেন। এবং এইচবি সম্পর্কটি ট্রানজিটিভ তাই আপনি এইচবি (ডাব্লু 1, আর 1) এবং এইচবি (ডাব্লু 2, আর 1) প্রবর্তন করেন। অনুশীলনে জাভা কনকুরেন্সিতে এটি সংক্ষিপ্তসারিত হয়েছে (৩.৩.৩. নিরাপদ প্রকাশনা আইডিয়ামস)।
Assylias

2
আহ, যদি এইচবি এইভাবে ট্রানজিটিভ হয় তবে এটি যথেষ্ট শক্তিশালী 'বাধা', হ্যাঁ। আমার বলতে হবে যে, জেএলএসের 17.4.5 জেবি এই সম্পত্তিটি নির্ধারণের জন্য সংজ্ঞা দেয় তা নির্ধারণ করা সহজ নয়। এটি অবশ্যই 17.4.5 এর শুরুতে প্রদত্ত সম্পত্তিগুলির তালিকায় নেই। কিছু ব্যাখ্যামূলক নোটের পরে আরও নিচে ট্রানজিটিভ বন্ধের কথা উল্লেখ করা হয়! যাইহোক, জেনে রাখা ভাল, উত্তরের জন্য ধন্যবাদ! :)। দ্রষ্টব্য: অ্যাসিলিয়াসের মন্তব্য প্রতিফলিত করতে আমি আমার উত্তর আপডেট করব।
পৌল

-2

আপনি লেখাগুলি এবং পড়ার সিঙ্ক্রোনাইজ করতে কোনও অবজেক্ট ব্যবহার করতে পারেন। অন্যথায়, অন্যরা যেমন আগে বলেছিল, কারেন্টপোস-এ একটি লেখাগুলি p.x + 1 এবং py দুটি পাঠের মাঝামাঝি সময়ে ঘটবে

new Thread() {
    void f(Point p) {
        if (p.x+1 != p.y) {
            System.out.println(p.x+" "+p.y);
            System.exit(1);
        }
    }
    @Override
    public void run() {
        while (currentPos == null);
        while (true)
            f(currentPos);
    }
}.start();
Object sem = new Object();
while (true) {
    synchronized(sem) {
        currentPos = new Point(currentPos.x+1, currentPos.y+1);
    }
}

আসলে এই কাজ করে। আমার প্রথম প্রয়াসে আমি রিডটিকে সিঙ্ক্রোনাইজড ব্লকের ভিতরে রেখেছিলাম, কিন্তু পরে আমি বুঝতে পারি যে এটি সত্যই প্রয়োজনীয় ছিল না।
জার্মানি ফ্রোনজা

1
-1 জেভিএম প্রমাণ করতে পারে যে semএটি ভাগ করা হয়নি এবং সিঙ্ক্রোনাইজড স্টেটমেন্টটিকে নো-অপ্ট হিসাবে গণ্য করে ... এটি সমস্যা সমাধানের বিষয়টি খাঁটি ভাগ্য।
Assylias

4
আমি বহু-থ্রেড প্রোগ্রামিংকে ঘৃণা করি, ভাগ্যের কারণে অনেক বেশি কাজ করে।
জোনাথন অ্যালেন

-3

আপনি কারেন্টপোসে দুবার অ্যাক্সেস করছেন এবং কোনও গ্যারান্টি দিচ্ছেন না যে এটি দুটি প্রবেশের মধ্যে আপডেট করা নেই।

উদাহরণ স্বরূপ:

  1. x = 10, y = 11
  2. কর্মী থ্রেড 10 হিসাবে px মূল্যায়ন করে
  3. প্রধান থ্রেড আপডেট এক্সিকিউট করে, এখন x = 11 এবং y = 12
  4. কর্মী থ্রেড পাই হিসাবে 12 হিসাবে মূল্যায়ন করে
  5. কর্মী থ্রেড বিজ্ঞপ্তি যে 10 + 1! = 12, তাই মুদ্রণ এবং প্রস্থান।

আপনি মূলত দুটি পৃথক পয়েন্টের তুলনা করছেন ।

নোট করুন যে এমনকি কারেন্টপোসকেও অস্থির করে তোলা আপনাকে এ থেকে রক্ষা করবে না, কারণ এটি কর্মী থ্রেড দ্বারা পৃথক দুটি পৃথক পঠন।

একটি যোগ করুন

boolean IsValid() { return x+1 == y; }

আপনার পয়েন্ট ক্লাসে পদ্ধতি। এটি নিশ্চিত করবে যে x + 1 == y পরীক্ষা করার সময় কারেন্টপোসের একমাত্র মান ব্যবহৃত হয়।


কারেন্টপোস কেবল একবার পঠিত হয়, এর মান পি তে অনুলিপি করা হয়। পি দুটিবার পড়া হয় তবে এটি সর্বদা একই অবস্থানের দিকে ইঙ্গিত করে।
জোনাথন অ্যালেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.