Почему синхронизированный блок не блокирует указанный объект? - PullRequest
0 голосов
/ 28 октября 2019

Я работаю над корпоративным веб-приложением, в котором пользователи могут создавать и распечатывать PDF-файлы с помощью API iText 1.3. В последнее время я столкнулся с большой проблемой параллелизма, которая отображает неправильные данные для пользователя, другими словами, он отображает те же данные длявсе пользователи.

сценарий состоит в создании файла PDF более чем одним пользователем одновременно, вот метод вызова:

public PDFFile generate(final long cartId, final FicheClient ficheClient) {

        PDFFile result = null;
        Set<CartOperation> opeToPrint = new HashSet<CartOperation>();
        Set<CartPostage> postToPrint = new HashSet<CartPostage>();
        Set<CartProduct> prodToPrint = new HashSet<CartProduct>();
        this.init();

        cart = cart.get(cartId);

        if (cart.getOperations() != null) {
            for (CartOperation ope : cart.getOperations()) {
                if (ope.getEntryState() == 0) {
                    opeToPrint.add(ope);
                }
            }
            cart.setOperations(opeToPrint);
        }

        if (cart.getPostages() != null) {
            for (CartPostageED post : cart.getPostages()) {
                if (post.getEntryState() == 0) {
                    postToPrint.add(post);
                }
            }
            cart.setPostages(postToPrint);
        }

        if (cart.getProducts() != null) {
            for (CartProduct prod : cart.getProducts()) {
                if (prod.getState() == 0) {
                    prodToPrint.add(prod);
                }
            }
            cart.setProducts(prodToPrint);
        }

        address = address.findBySiteIdAndAddressTypeCode(cart
                .getSite().getSiteId(), AddressTypeEnum.GEO
                .getCode());
        phone = phone.findBySiteIdAndPhoneTypeCode(cart.getSite()
                .getSiteId(), PhoneTypeEnum.STANDARD.getCode());
        // Récupération des taux de TVA
        vatLevels = this.findVatLevels(cart.getSite().getRegCode());
        if (ficheClient != null) {
            result = super.generateInternal(ficheClient);
        }
        return result;
    }

После проверки всехкод, который я подозреваю, что PdfWriter.getInstance (doc, baos);является одноэлементным и не синхронизируется, за исключением того, что я не нашел подозрительного кода, который мог бы вызвать это, вот метод

 protected PDFFile generateInternal(final T data) {
        PDFFile result = null;
        final String methodName = "generate";

        final Document doc = this.createDocument();
        final CustomDocument tmpDoc = (CustomDocument) this.createDocument();
        tmpDoc.setMock(true);
        this.updateDocumentMargins(tmpDoc);
        final ByteArrayOutputStream tmpBaos = new ByteArrayOutputStream();
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {

            FontFactory.defaultEmbedding = this.getFontEmbedding();

            // Ouverture du document
             synchronized (PdfWriter.getInstance(doc, baos)) {
            final PdfWriter writer1 = PdfWriter.getInstance(doc, new 
            FileOutputStream(new File("C:/bordereau de vente"+i+".pdf")));

            tmpWriter.setViewerPreferences(PdfWriter.PageLayoutSinglePage);
            this.buildMetadata(tmpDoc, tmpWriter, data);
            tmpDoc.open();

            this.buildDocument(tmpDoc, tmpWriter, data);

            // Fermeture du stream et du document.
            tmpBaos.flush();
            tmpBaos.close();
            tmpDoc.close();

            final PdfReader readerTemp = new PdfReader(tmpBaos.toByteArray());
            final int nbPages = readerTemp.getNumberOfPages();

            this.updateDocumentMargins(doc);
            final PdfWriter writer = PdfWriter.getInstance(doc, baos);
            writer.setViewerPreferences(PdfWriter.PageLayoutSinglePage);
            this.buildMetadata(doc, writer, data);
            doc.open();
            this.addPageEvent(writer, nbPages);
            this.buildDocument(doc, writer, data);

            // Fermeture du stream et du document.
            baos.flush();
            baos.close();
            doc.close();

            result = new PDFFile(getPdfTypeEnum(), getDate());
            result.setFileName(this.fileName);
            result.setFileContent(baos.toByteArray());

        } catch (IOException ioe) {
            LOGGER.error(RGPLogPhaseEnum.ACTION, null, null, methodName,
                    RGPLogEtapeEnum.PHASE_ENCOURS, "Erreur lors de la lecture du 
                    fichier PDF.");
            ioe.printStackTrace();
        } catch (DocumentException e) {
            LOGGER.error(RGPLogPhaseEnum.ACTION, null, null, methodName,
                    RGPLogEtapeEnum.PHASE_ENCOURS, "Erreur lors de la création du fichier PDF.");
            e.printStackTrace();
        } finally {
            if (doc.isOpen()) {
                doc.close();
            }
            try {
                baos.close();
            } catch (IOException ioe) {
                System.out.println();
                LOGGER.error(RGPLogPhaseEnum.ACTION, null, null, methodName,
                        RGPLogEtapeEnum.PHASE_ENCOURS,
                        "Erreur lors de la fermeture du document PDF généré.");
            }
        }
        return result;
    }

Когда я вошел в систему с разными пользователями на одном сервере, вВ режиме отладки я установил точку останова в этой строке final PdfWriter writer = PdfWriter.getInstance (документ, новый FileOutputStream (новый файл ("C: / bordereau" + i + ". pdf"))); Когда ясработало первое действие (user1) сгенерированный файл содержит данные второго, что означает, что возвращаемый объект PdfWriter.getInstance (doc, baos); не синхронизирован, я добавил ключевое слово Synchronized atметод и уровень блока, но он не работает.

Почему объект не блокируется, когда он вызывается первым пользователем? я что-то упустил?

...